2

我有一个平衡良好的面板数据集,其中包含 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]

欢迎所有解决方案,但 data.table 解决方案是高度首选的;数据文件很大。

4

2 回答 2

5

这将做到:

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

我只是跑去rle找所有连续NA的 's 并选择了最大长度。


这是对恢复上述日期范围的评论问题的相当复杂的答案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]
于 2013-05-29T17:32:33.077 回答
3

您可以使用此处rle建议的修改(并粘贴在下面)来计算值。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")
}
于 2013-05-29T17:31:48.170 回答