使用最近的非 NA 观测值填充 data.table 中的 NA 值

3

我有一个 data.table,如下:

library(data.table)
dt.tst <- CJ(Type = c("A", "B"),
             Range_val = seq(0,20000, by = 1000))


dt.tst[Range_val == 2000 & Type == "A", Value := 0.987]
dt.tst[Range_val == 2000 & Type == "B", Value := 1.987]

dt.tst[Range_val == 9000 & Type == "A", Value := 1.056]
dt.tst[Range_val == 9000 & Type == "B", Value := 2.138]

dt.tst[Range_val == 16000 & Type == "A", Value := 1.563]
dt.tst[Range_val == 16000 & Type == "B", Value := 2.089]

我想填充Value列中的NA值:
  • 根据Range_val和Type找到最接近的非na值
  • 如果有多个值与目标相等,则选择Range_val最高的值(但这不是必须的,速度更重要)

我可以使用for循环来完成此操作,但速度较慢,我希望有一种更简洁,更快捷的方式。在data.table中如何实现?

始终会有非na值,但间隔可能不同。


请参见:https://dev59.com/Amkw5IYBdhLWcg3wMHkY。 - Maël
@Maël 我不认为这些解决方案会起作用,因为我需要按组来做。但是我可能可以从中得到我的问题的线索。 - ErrantBard
1
由 Range_val 列和 Type 分组 对我来说不太清楚 - 会有42个大小为1的组。请分享预期输出。 - ismirsehregal
1
在 data.table 中,nafill 目前仅支持 nocb 和 locf,因此这似乎是一个不错的功能请求。 - jangorecki
2个回答

6
dt.tst[is.na(Value), Value := dt.tst[!is.na(Value)][dt.tst[is.na(Value)], roll = "nearest", on = .(Type, Range_val)]$Value]

输出

dt.tst

#     Type Range_val Value
#  1:    A         0 0.987
#  2:    A      1000 0.987
#  3:    A      2000 0.987
#  4:    A      3000 0.987
#  5:    A      4000 0.987
#  6:    A      5000 0.987
#  7:    A      6000 1.056
#  8:    A      7000 1.056
#  9:    A      8000 1.056
# 10:    A      9000 1.056
# 11:    A     10000 1.056
# 12:    A     11000 1.056
# 13:    A     12000 1.056
# 14:    A     13000 1.563
# 15:    A     14000 1.563
# 16:    A     15000 1.563
# 17:    A     16000 1.563
# 18:    A     17000 1.563
# 19:    A     18000 1.563
# 20:    A     19000 1.563
# 21:    A     20000 1.563
# 22:    B         0 1.987
# 23:    B      1000 1.987
# 24:    B      2000 1.987
# 25:    B      3000 1.987
# 26:    B      4000 1.987
# 27:    B      5000 1.987
# 28:    B      6000 2.138
# 29:    B      7000 2.138
# 30:    B      8000 2.138
# 31:    B      9000 2.138
# 32:    B     10000 2.138
# 33:    B     11000 2.138
# 34:    B     12000 2.138
# 35:    B     13000 2.089
# 36:    B     14000 2.089
# 37:    B     15000 2.089
# 38:    B     16000 2.089
# 39:    B     17000 2.089
# 40:    B     18000 2.089
# 41:    B     19000 2.089
# 42:    B     20000 2.089

3
很好地使用了“roll”,在内存和时间方面都很高效,我认为值得一加! - ThomasIsCoding

3

如果我正确理解您的目标,即将 Value 列中的 NA 赋值为其最近的非 NA 值,那么您可以尝试像下面这样使用 max.colouter

dt.tst[
  ,
  Value2 := replace(
    Value,
    is.na(Value),
    na.omit(Value)[max.col(-abs(outer(which(is.na(Value)), which(!is.na(Value)), `-`)), "last")]
  ), Type
][]

这提供了

    Type Range_val Value Value2
 1:    A         0    NA  0.987
 2:    A      1000    NA  0.987
 3:    A      2000 0.987  0.987
 4:    A      3000    NA  0.987
 5:    A      4000    NA  0.987
 6:    A      5000    NA  0.987
 7:    A      6000    NA  1.056
 8:    A      7000    NA  1.056
 9:    A      8000    NA  1.056
10:    A      9000 1.056  1.056
11:    A     10000    NA  1.056
12:    A     11000    NA  1.056
13:    A     12000    NA  1.056
14:    A     13000    NA  1.563
15:    A     14000    NA  1.563
16:    A     15000    NA  1.563
17:    A     16000 1.563  1.563
18:    A     17000    NA  1.563
19:    A     18000    NA  1.563
20:    A     19000    NA  1.563
21:    A     20000    NA  1.563
22:    B         0    NA  1.987
23:    B      1000    NA  1.987
24:    B      2000 1.987  1.987
25:    B      3000    NA  1.987
26:    B      4000    NA  1.987
27:    B      5000    NA  1.987
28:    B      6000    NA  2.138
29:    B      7000    NA  2.138
30:    B      8000    NA  2.138
31:    B      9000 2.138  2.138
32:    B     10000    NA  2.138
33:    B     11000    NA  2.138
34:    B     12000    NA  2.138
35:    B     13000    NA  2.089
36:    B     14000    NA  2.089
37:    B     15000    NA  2.089
38:    B     16000 2.089  2.089
39:    B     17000    NA  2.089
40:    B     18000    NA  2.089
41:    B     19000    NA  2.089
42:    B     20000    NA  2.089
    Type Range_val Value Value2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接