趋势长度 - 面板数据

时间:2013-05-29 17:13:04

标签: r time-series data.table zoo

我有一个平衡的面板数据集,其中包含NA观察结果。我将使用LOCF,并想知道每个面板中有多少个连续的NA,然后再进行观察。 LOCF是一种程序,其中可以使用“最后一次观察结果”来“填充”缺失值。这对于某些时间序列应用程序来说是有意义的;也许我们有5分钟增量的天气数据:对缺失观测值的一个很好的猜测可能是5分钟前的观察结果。

显然,在一个小组内进行观察一小时比在同一小组中将同一观察结果推进到下一年更有意义。

我知道您可以使用zoo :: na.locf设置“maxgap”参数,但是,我想更好地了解我的数据。请看一个简单的例子:

require(data.table)
set.seed(12345)

### Create a "panel" data set
data <- data.table(id = rep(1:10, each = 10),
                   date = seq(as.POSIXct('2012-01-01'),
                              as.POSIXct('2012-01-10'),
                              by = '1 day'),
                   x  = runif(100))

### Randomly assign NA's to our "x" variable
na <- sample(1:100, size = 52)
data[na, x := NA]

### Calculate the max number of consecutive NA's by group...this is what I want:
### ID       Consecutive NA's
  #  1       1
  #  2       3
  #  3       3
  #  4       3
  #  5       4
  #  6       5
  #  ...
  #  10      2

### Count the total number of NA's by group...this is as far as I get:
data[is.na(x), .N, by = id]

欢迎所有解决方案,但数据表解决方案是首选;数据文件很大。

2 个答案:

答案 0 :(得分:5)

这样做:

data[, max(with(rle(is.na(x)), lengths[values])), by = id]

我刚刚运行rle找到所有连续的NA并选择了最大长度。


对于恢复上述max的日期范围的评论问题,这是一个相当复杂的答案:

data[, {
         tmp = rle(is.na(x));
         tmp$lengths[!tmp$values] = 0;  # modify rle result to ignore non-NA's
         n = which.max(tmp$lengths);    # find the index in rle of longest NA sequence

         tmp = rle(is.na(x));                   # let's get back to the unmodified rle
         start = sum(tmp$lengths[0:(n-1)]) + 1; # and find the start and end indices
         end   = sum(tmp$lengths[1:n]);

         list(date[start], date[end], max(tmp$lengths[tmp$values]))
       }, by = id]

答案 1 :(得分:3)

您可以使用rle修改建议here(并在下方粘贴)来计算NA值。

foo  <- data[, rle(x), by=id]
foo[is.na(values), max(lengths), by=id]

#     id V1
# 1:  1  1
# 2:  2  3
# 3:  3  3
# 4:  4  3
# 5:  5  4
# 6:  6  5
# 7:  7  3
# 8:  8  5
# 9:  9  2
# 10: 10  2

修订后的rle功能:

rle<-function (x)
{
     if (!is.vector(x)&&  !is.list(x))
         stop("'x' must be an atomic vector")
     n<- length(x)
     if (n == 0L)
         return(structure(list(lengths = integer(), values = x),
             class = "rle"))

     #### BEGIN NEW SECTION PART 1 ####
     naRepFlag<-F
     if(any(is.na(x))){
         naRepFlag<-T
         IS_LOGIC<-ifelse(typeof(x)=="logical",T,F)

         if(typeof(x)=="logical"){
             x<-as.integer(x)
             naMaskVal<-2
         }else if(typeof(x)=="character"){
             naMaskVal<-paste(sample(c(letters,LETTERS,0:9),32,replace=T),collapse="")
         }else{
             naMaskVal<-max(0,abs(x[!is.infinite(x)]),na.rm=T)+1
         }

         x[which(is.na(x))]<-naMaskVal
     }
     #### END NEW SECTION PART 1 ####

     y<- x[-1L] != x[-n]
     i<- c(which(y), n)

     #### BEGIN NEW SECTION PART 2 ####
     if(naRepFlag)
         x[which(x==naMaskVal)]<-NA

     if(IS_LOGIC)
         x<-as.logical(x)
     #### END NEW SECTION PART 2 ####

     structure(list(lengths = diff(c(0L, i)), values = x[i]),
         class = "rle")
}