使用最近的非 na 观察值,用 NA 值填充 data.table

Err*_*ard 3 r data.table

我有一个 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]
Run Code Online (Sandbox Code Playgroud)

我想在值列中填写 NA::

  • 使用 Range_val 列和类型最接近的非 na 值。
  • 如果出现平局,则应使用最高的 Range_val 及其相应的 Value(但这不是一个破坏因素,速度更重要)。

我可以用 for 循环做到这一点,非常简单,但速度很慢。所以我想要一种更干净的方式来做到这一点(并且更快)。这样做的一个好的 data.table 方式是什么?

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

Mer*_*org 6

dt.tst[is.na(Value), Value := dt.tst[!is.na(Value)][dt.tst[is.na(Value)], roll = "nearest", on = .(Type, Range_val)]$Value]
Run Code Online (Sandbox Code Playgroud)

输出

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
Run Code Online (Sandbox Code Playgroud)

  • 我认为“roll”的使用很好,在记忆和时间意义上都很高效。+1! (3认同)