如何用data.table高效填充NA值(取最近非NA观测值)
问题描述
我有如下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值,要求:
- 按
Type分组,根据Range_val取最近的非NA值填充 - 若距离相同,优先取较大
Range_val对应的Value(优先保证速度)
目前用for循环实现但速度慢,求高效的data.table方案,数据中必有非NA值,间隔不固定。
高效实现方案
利用data.table的分组滚动连接可以高效解决这个问题,这是针对近邻匹配场景的优化操作:
# 提取各分组下的非NA值记录 non_na_dt <- dt.tst[!is.na(Value)] # 按Type分组执行滚动连接,匹配最近的非NA值 dt.tst[, Value := non_na_dt[.SD, on = .(Type, Range_val), roll = "nearest", x.Value]]
关键说明
- 滚动连接逻辑:
roll = "nearest"参数会自动为每条NA记录匹配同组内Range_val最接近的非NA记录,底层实现高效,远快于for循环 - 距离相同的优先级:当两个非NA值与目标
Range_val距离相等时,data.table的滚动连接默认会选取Range_val更大的那条记录,刚好满足需求 - 兼容性:该方法适用于任意间隔的非NA值,只要每组存在至少一个非NA值即可
如果需要显式控制优先级,可预先对非NA记录按Range_val降序排列,效果一致且不影响性能:
non_na_dt <- dt.tst[!is.na(Value)][order(Type, -Range_val)] dt.tst[, Value := non_na_dt[.SD, on = .(Type, Range_val), roll = "nearest", x.Value]]
内容的提问来源于stack exchange,提问作者ErrantBard
相关产品推荐
相关产品推荐

