ř校正不一致的数据记录

问题描述 投票:1回答:2

我记录每5分钟四个变量。当我绘制在四个变量的R A的时间序列我实现可变3记录不一致的数据,由于所述数据集合中的一个错误(记录装置的错误/传感器错误)。我怎样才能纠正数据记录?

变3中的数据记录显示,一些不正常的跳跃,并且它不是研究变量的物理性作用。图像显示的数据记录每天的振荡的一周。不应该有连续两个读数之间的这种跳高。我尝试了一些异常[R包前一段时间,却得到了不与它导致...

enter image description here

当我绘制整个时间序列的结果是雪上加霜。

enter image description here

任何帮助将不胜感激。谢谢

我从图像1共享数据:

Figure 1 csv data

r plot outliers
2个回答
2
投票

读取数据并绘制后,我看到这一点:

df <- read.csv("~/StackOverflow/RaülOo.csv")
df$TIMESTAMP <- as.POSIXct(df$TIMESTAMP)
library(dplyr)
library(tidyr)
library(ggplot2)
gather(df, k, v, -X, -TIMESTAMP) %>%
  ggplot(aes(TIMESTAMP, v, color=k)) +
  geom_path()

unfiltered

它是那样简单“任何超过-50”?在十分位数是这样的:

quantile(unlist(df[,3:6]), seq(0,1,len=11))
#        0%       10%       20%       30%       40%       50%       60%       70% 
# -122.7000  -22.9600  -17.5500  -13.4200  -10.0700   -5.9615    3.4800   16.0500 
#       80%       90%      100% 
#   26.6040   35.6860   81.4000 

该IQR在箱图周围37.类似“晶须”,它可能是不现实的假设"1.5 IQR",那就是:下面“的1.5倍IQR下四分位数下面”的值(与上述同样地,虽然不存在于该数据)可能安全地算不算异常。

(q <- quantile(unlist(df[,3:6]), c(0.25, 0.75)))
#      25%      75% 
# -15.4000  22.0025 
unname( q[1] - 1.5*diff(q) ) # "unname" only to remove the now-misleading percentile label
# -71.50375 
gather(df, k, v, -X, -TIMESTAMP) %>%
  filter(v > q[1] - 1.5*diff(q)) %>%
  ggplot(aes(TIMESTAMP, v, color=k)) +
  geom_path()

partially filtered

因此,也许1.5不强,不足以真正识别异常值,但它取决于你的需求。如果你需要的是一个清理的地块(和一些离群不伤元气),那么我建议使用标准“的1.5倍IQR”就足够了。如果您想更多控制它,可能使用更接近于1将工作。

gather(df, k, v, -X, -TIMESTAMP) %>%
  filter(v > q[1] - diff(q)) %>%
  ggplot(aes(TIMESTAMP, v, color=k)) +
  geom_path()

filtered

如果您需要这回在“宽”的格式,你可以这样做:

gather(df, k, v, -X, -TIMESTAMP) %>%
  filter(v > -50) %>%
  spread(k, v) %>%
  slice(37:43) # just for demonstration
#    X           TIMESTAMP   four    one  three    two
# 1 37 2018-07-15 03:05:00 -21.68 -32.04 -23.11 -12.87
# 2 38 2018-07-15 03:10:00 -21.79 -31.71 -23.11 -12.87
# 3 39 2018-07-15 03:15:00 -21.79 -31.71 -23.11 -12.87
# 4 40 2018-07-15 03:20:00 -21.79 -31.71 -23.11 -12.87
# 5 41 2018-07-15 03:25:00 -17.43 -25.37     NA -10.29
# 6 42 2018-07-15 03:30:00 -21.79 -31.71 -23.11 -12.87
# 7 43 2018-07-15 03:35:00 -21.79 -31.28 -23.11 -12.87

在您的异常现在NA是。更-简洁,非dplyr / tidyr替代可能是:

df[,3:6] <- lapply(df[,3:6], function(a) ifelse(a < -50, NA, a))

然后任何后续处理或绘制你需要考虑(忽略)NA值。


我会走一步,因为它可能是有趣的(给你)知道坏数据是如何频繁地(或定期)的到来。

newdat <- df %>%
  gather(k, v, -X, -TIMESTAMP) %>%
  mutate(v = if_else(v < q[1] - diff(q), NA_real_, v))
baddat <- filter(newdat, is.na(v))
newdat <- filter(newdat, !is.na(v))
baddat$v <- min(newdat$v) - 5 # arbitrary

ggplot(newdat, aes(TIMESTAMP, v, color = k)) +
  geom_path() +
  geom_point(data = baddat)

filtered with outlier dots

在这里你可以看到问题的数据点都位于无需缩放时的图表的其余部分。


笔记

  • 这似乎是一个快速的黑客,让你开始。举例来说,如果不是均匀的四个不同的测量是在完全不同的尺度,这将需要每列做。
  • 我用dplyr的数据忙玲,虽然他们都没有严格要求。这很容易被在基地-R进行相对简单的功能。使用ggplot2的规定长的数据,测功tidyr::gather(和tidyr::spread);如果是使用碱的图形,则可能不需要重塑数据(这表明每列的数据替换可能优选)。

1
投票

这里是一个可能的解决方案,但首先我们需要生成一个代表你的问题的一些数据。什么是关于您的方案很好的是,虚假的数据点是大的尖峰,相当明显的,甚至视觉。

生成数据

set.seed(15161)
x <- seq(pi/10,10*pi,by=pi/100)
y <- sin(x) # using sin() generates some osciliating data
z <- sample(c(0,-5),length(y),
            prob=c(0.99,0.01),replace=TRUE) # pepper the data with random spikes
y <- y + z
df <- data.frame(cbind(x,y,z))
length(which(df$z==-5)) # the number of spikes ~ 13
plot(df$x,df$y,type="l",ylim=c(-10,2),col="blue",xlab="x",ylab="y")
abline(h=0,lty=5)

enter image description here

除去杂散测量(清洁的数据)

在你目前的数据,相对于良好的测量背景的虚假数据点都非常大。这是你的测量一直很好的缓慢递增或递减的方式移动,然后通过布拉姆> 20台跳跃/下降。所以我写这将发现和删除表示上述某个阈值增加/减少任何数据点(在你的情况下,约20个单位,在我的工作上面的例子〜2个单位就足够了)的功能。

功能码是:

f <- function(df,clean,threshold){
  y <- df[,clean]
  for(i in 1:length(y)){
    if(is.na(y[i]) | is.na(y[i+1])){
      next
    }
    if(abs(y[i+1]-y[i])>threshold){
      y[i+1] <- NA
    }
  }
  return(df[!is.na(y),])
}
cleaned.df <- f(df,clean="y",threshold=2) # Run the function to clean the data
length(which(cleaned.df$z==-5)) # number of spikes in cleaned data is now 0

画出清洗结果

plot(cleaned.df$x,cleaned.df$y,type="l",ylim=c(-10,2),col="blue",xlab="x",ylab="y")
abline(h=0,lty=5)

enter image description here

注释和注意事项

  1. 确保您的数据依次运行函数之前排序(即按时间顺序排序的测量)
  2. 我建议你选择大约20个单位的阈值(只是你的图形的视觉检查这似乎是足够的。
  3. 清洁功能可能不会在除去2个或更多个连续的峰值有效。但是,您可以通过清洁功能多次运行数据,并应工作。
  4. 还有,我们可以制定更严格的方法,但我认为这解决办法是简单而有效。让我们知道,如果你仍然有问题,我们可以制定更严格的解决方案。

编辑1:

我刚才看到你上传了一些实际的数据。调整了功能略,以适应变化的测量标志尖峰。下面是为适用于您的数据,它看起来像它的作品给我的结果。

df <- read.csv("figure1data.csv")
plot(df$X,df$three,type="l",col="blue",xlab="x",ylab="y",ylim=c(-150,50))
    abline(h=0,lty=5)

enter image description here

cleaned.df1 <- f(df,clean="three",threshold=20)
plot(cleaned.df1$X,cleaned.df1$three,type="l",col="blue",xlab="x",ylab="y",
     ylim=c(-150,50))
abline(h=0,lty=5)

enter image description here

编辑2:响应OP评论

要删除其中连贯尖峰发生,只需重新运行在清理数据的功能的情况。

cleaned.df2 <- f(cleaned.df1,clean="three",threshold=20)

要恢复所有行的数据并将其转换尖刺变“三”点作为NA简单地将数据合并回如下。

New.df <- merge(df[,colnames(df)!="three"],
               cleaned.df2[,colnames(df) %in% c("X","three")],
               by="X",all.x=TRUE)

要检查预期,事情正在

df[which(!complete.cases(New.df)),] 
New.df[which(!complete.cases(New.df)),]

你清楚地看到,与变量“三”尖峰行现在在NANew.df

© www.soinside.com 2019 - 2024. All rights reserved.