11

我希望为我正在处理的数据集实施“最后一次观察结转”,该数据集的末尾有缺失值。

这是一个简单的代码(后面的问题):

LOCF <- function(x)
{
    # Last Observation Carried Forward (for a left to right series)
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward
    x[LOCF:length(x)] <- x[LOCF]
    return(x)
}


# example:
LOCF(c(1,2,3,4,NA,NA))
LOCF(c(1,NA,3,4,NA,NA))

现在这对简单的向量很有用。但是,如果我在哪里尝试在数据框中使用它:

a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA))
a
t(apply(a, 1, LOCF)) # will make a mess

它将我的数据框变成一个字符矩阵。

你能想出一种在 data.frame 上做 LOCF 而不把它变成矩阵的方法吗?(我可以使用循环等来纠正混乱,但希望有一个更优雅的解决方案)

4

7 回答 7

23

这已经存在:

library(zoo)
na.locf(data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA)))
于 2010-05-05T19:31:33.810 回答
10

如果您不想仅为 na.locf 函数加载像 zoo 这样的大包,这里有一个简短的解决方案,如果输入向量中有一些前导 NA,它也可以工作。

na.locf <- function(x) {
  v <- !is.na(x)
  c(NA, x[v])[cumsum(v)+1]
}
于 2017-01-19T21:38:43.270 回答
9

添加新tidyr::fill()函数以将列中的最后一个观察值结转以填充NAs:

a <- data.frame(col1 = rep("a",4), col2 = 1:4, 
                col3 = 1:4, col4 = c(1,NA,NA,NA))
a
#   col1 col2 col3 col4
# 1    a    1    1    1
# 2    a    2    2   NA
# 3    a    3    3   NA
# 4    a    4    4   NA

a %>% tidyr::fill(col4)
#   col1 col2 col3 col4
# 1    a    1    1    1
# 2    a    2    2    1
# 3    a    3    3    1
# 4    a    4    4    1
于 2017-07-14T10:16:15.283 回答
4

有很多包实现了这个功能。(具有相同的基本功能,但附加选项有所不同)

  • 时空::na.locf
  • imputeTS::na.locf
  • 动物园::na.locf
  • xts::na.locf
于 2016-11-10T17:53:39.850 回答
2

这个问题很老,但对于后代......最好的解决方案是使用带有roll = T的data.table包。

于 2013-04-09T15:26:11.453 回答
0

我最终使用循环解决了这个问题:

fillInTheBlanks <- function(S) {
  L <- !is.na(S)
  c(S[L][1], S[L])[cumsum(L)+1]
}


LOCF.DF <- function(xx)
{
    # won't work well if the first observation is NA

    orig.class <- lapply(xx, class)

    new.xx <- data.frame(t( apply(xx,1, fillInTheBlanks) ))

    for(i in seq_along(orig.class))
    {
        if(orig.class[[i]] == "factor") new.xx[,i] <- as.factor(new.xx[,i])
        if(orig.class[[i]] == "numeric") new.xx[,i] <- as.numeric(new.xx[,i])
        if(orig.class[[i]] == "integer") new.xx[,i] <- as.integer(new.xx[,i])   
    }

    #t(na.locf(t(a)))

    return(new.xx)
}

a <- data.frame(rep("a",4), 1:4,1:4, c(1,NA,NA,NA))
LOCF.DF(a)
于 2010-05-05T21:01:02.033 回答
0

而不是apply()您可以使用lapply()然后将结果列表转换为data.frame.

LOCF <- function(x) {
    # Last Observation Carried Forward (for a left to right series)
    LOCF <- max(which(!is.na(x))) # the location of the Last Observation to Carry Forward
    x[LOCF:length(x)] <- x[LOCF]
    return(x)
}

a <- data.frame(rep("a",4), 1:4, 1:4, c(1, NA, NA, NA))
a
data.frame(lapply(a, LOCF))
于 2015-07-22T13:48:28.947 回答