从1个数据帧中的多个时间序列的开始和结束中有效地删除缺失值

时间:2012-05-30 06:55:21

标签: r dataframe data.table time-series zoo

使用R,我试图从包含多个时间序列的数据帧的开头和结尾修剪NA值。我已经使用for循环和zoo包实现了我的目标,但正如预期的那样,它在大数据帧上的效率极低。

我的数据框看起来像这样,包含3列,每个时间序列都由它的唯一ID标识。在这种情况下,AAA,B和CCC。

id   date          value
AAA  2010/01/01    NA
AAA  2010/02/01    34
AAA  2010/03/01    35
AAA  2010/04/01    30
AAA  2010/05/01    NA
AAA  2010/06/01    28
B    2010/01/01    NA
B    2010/02/01    0
B    2010/03/01    1
B    2010/04/01    2
B    2010/05/01    3
B    2010/06/01    NA
B    2010/07/01    NA
B    2010/07/01    NA
CCC  2010/01/01    0
CCC  2010/02/01    400
CCC  2010/03/01    300
CCC  2010/04/01    200
CCC  2010/05/01    NA

我想知道,如何有效地从每个时间序列的开头和结尾删除NA值,在本例中为AAA,B和CCC。所以看起来应该是这样的。

id   date          value
AAA  2010/02/01    34
AAA  2010/03/01    35
AAA  2010/04/01    30
AAA  2010/05/01    NA
AAA  2010/06/01    28
B    2010/02/01    0
B    2010/03/01    1
B    2010/04/01    2
B    2010/05/01    3
CCC  2010/01/01    0
CCC  2010/02/01    400
CCC  2010/03/01    300
CCC  2010/04/01    200

2 个答案:

答案 0 :(得分:7)

我会这样做,这应该非常快:

require(data.table)
DT = as.data.table(your data)   # please provide something pastable

DT2 = DT[!is.na(value)]
setkey(DT,id,date)
setkey(DT2,id,date)
tokeep = DT2[DT,!is.na(value),rolltolast=TRUE,mult="last"]
DT = DT[tokeep]

这可以通过向前推进每个群体中流行的非NA,但不会超过最后一个。

mult="last"是可选的。如果使用v1.8.0(在CRAN上),它应该加速它。有和没有它的时间感兴趣。默认情况下,data.table加入群组(mult="all"),但在这种情况下,我们会加入群组的所有列,而且,我们知道密钥是唯一的;即,密钥中没有重复。在v1.8.1(在开发中),没有必要知道这一点,它会照顾你更多。

答案 1 :(得分:0)

如果您的数据位于数据框data

fun <- function(x)
{
    x$value[is.na(x$value)] <- "NA"
    tmp <- rle(x$value)
    values <- tmp$values
    lengths <- tmp$lengths
    n <- length(values)

    nr <- nrow(x)
    id <- c()
    if(values[1] == "NA") id <- c(id, 1:lengths[1])
    if(values[n] == "NA") id <- c(id, (nr-lengths[n]+1):nr)
    if(length(id) == 0)return(x)
    x[-id,]
}

do.call(rbind,
        by(data, INDICES=data$id,
           FUN=fun))

我猜不是最优雅的解决方案。心情this post