【问题标题】:na.locf fill NAs up to maxgap even if gap > maxgap, with groupsna.locf 将 NA 填充到 maxgap,即使 gap > maxgap,组
【发布时间】:2016-12-13 19:54:17
【问题描述】:

我已经看到了解决此问题的方法,但无法使其适用于团体 (Fill NA in a time series only to a limited number),并认为必须有一种更简洁的方法来做到这一点?

假设我有以下 dt:

dt <- data.table(ID = c(rep("A", 10), rep("B", 10)), Price = c(seq(1, 10, 1), seq(11, 20, 1)))
dt[c(1:2, 5:10), 2] <- NA 
dt[c(11:13, 15:19) ,2] <- NA 
dt
    ID Price
 1:  A    NA
 2:  A    NA
 3:  A     3
 4:  A     4
 5:  A    NA
 6:  A    NA
 7:  A    NA
 8:  A    NA
 9:  A    NA
10:  A    NA
11:  B    NA
12:  B    NA
13:  B    NA
14:  B    14
15:  B    NA
16:  B    NA
17:  B    NA
18:  B    NA
19:  B    NA
20:  B    20

我想做的是从最近的非NA 值向前和向后填充NAs both,但最多只能向前或向后两行返回。

我还需要按组(ID)来完成。

我曾尝试使用na.locf/na.approxmaxgap = x 等,但它不能填补NAs,非NA 值之间的差距大于maxgap。而即使非NA 值之间的差距大于maxgap,我也想向前和向后填充这些,但仅相差两行。

最终结果应该类似于:

    ID Price Price_Fill
 1:  A    NA          3
 2:  A    NA          3
 3:  A     3          3
 4:  A     4          4
 5:  A    NA          4
 6:  A    NA          4
 7:  A    NA         NA
 8:  A    NA         NA
 9:  A    NA         NA
10:  A    NA         NA
11:  B    NA         NA
12:  B    NA         14
13:  B    NA         14
14:  B    14         14
15:  B    NA         14
16:  B    NA         14
17:  B    NA         NA
18:  B    NA         20
19:  B    NA         20
20:  B    20         20

实际上,我的数据集非常庞大,我希望能够按组向前和向后填充 NAs 最多 672 行,但不会更多。

谢谢!

【问题讨论】:

    标签: r data.table na


    【解决方案1】:

    对于显示的示例,我们按“ID”分组,以n = 0:2 获取“价格”的shift,并将type 作为“引导”创建3 个临时列,从中获取pmax ,使用输出做shifttype = 'lag'(默认为'lag')和相同的n,得到pmin 并将其分配为'Price_Fill'

    dt[, Price_Fill := do.call(pmin, c(shift(do.call(pmax, c(shift(Price, n = 0:2, 
                      type = "lead"), na.rm=TRUE)), n= 0:2), na.rm = TRUE)) , by = ID]
    dt
    #    ID Price Price_Fill
    #1:  A    NA          3
    #2:  A    NA          3
    #3:  A     3          3
    #4:  A     4          4
    #5:  A    NA          4
    #6:  A    NA          4
    #7:  A    NA         NA
    #8:  A    NA         NA
    #9:  A    NA         NA
    #10: A    NA         NA
    #11: B    NA         NA
    #12: B    NA         14
    #13: B    NA         14
    #14: B    14         14
    #15: B    NA         14
    #16: B    NA         14
    #17: B    NA         NA
    #18: B    NA         20
    #19: B    NA         20
    #20: B    20         20
    

    更通用的方法是在 .I 上执行 pmin/pmax,因为“价格”可能不同,而不是 OP 帖子中显示的序列号。

    i1 <- dt[,  do.call(pmin, c(shift(do.call(pmax, c(shift(NA^(is.na(Price))* 
        .I, n = 0:2, type = "lead"), na.rm = TRUE)), n = 0:2), na.rm = TRUE)), ID]$V1
    
    dt$Price_Fill <  dt$Price[i1]
    dt$Price_Fill
    #[1]  3  3  3  4  4  4 NA NA NA NA NA 14 14 14 14 14 NA 20 20 20
    

    即假设我们改变“价格”,它会有所不同

    dt$Price[3] <- 10
    dt$Price[14] <- 7
    dt$Price_Fill <- dt$Price[i1]
    dt$Price_Fill
    #[1] 10 10 10  4  4  4 NA NA NA NA NA  7  7  7  7  7 NA 20 20 20
    

    【讨论】:

    • @akrun 有没有办法使用 dplyr/tidyverse 做到这一点?
    • @krenova 是的,但是 dplyr 中的 lag 不采用“n”值的向量。所以,你可能需要一个一个循环或创建
    猜你喜欢
    • 1970-01-01
    • 2018-11-02
    • 2019-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    相关资源
    最近更新 更多