如何按locf_N指定的可变次数向前填充data.table中的NA值?
可变次数的向前填充(LOCF)实现方案
嗨,我完全懂你的困扰——zoo包的na.locf确实只能设置全局统一的maxgap,没法根据每行的locf_N来动态调整填充次数。不过用data.table的原生功能就能轻松实现你的需求,下面给你两种直观的方法:
方法一:基于间隔距离判断填充
这个思路是先计算每个NA距离最近的前一个有效值的行数间隔,再和对应有效值允许的填充次数(locf_N)对比,只有间隔不超过允许次数时才填充:
library(data.table) library(zoo) # 你的原始数据 test <- data.table( value = c(5,NA,8,NA,NA,8,6,NA,NA,10), locf_N = c(1,NA,1,NA,NA,1,2,NA,NA,2) ) # 直接在原表修改value列 test[, value := { # 先得到全局向前填充的value值 locf_val <- na.locf(value, na.rm = FALSE) # 向前填充locf_N,让每个NA位置拿到对应有效值的允许填充次数 locf_n <- na.locf(locf_N, na.rm = FALSE) # 计算每个位置与前一个有效值位置的行数差 gap <- .I - shift(.I[!is.na(value)], fill = .I[1]) # 只有间隔<=允许次数时才用填充值,否则保留NA ifelse(gap <= locf_n, locf_val, NA) }] # 查看结果,和你期望的一致 test
方法二:按有效值分组填充
这个方法是把每个有效值和它允许填充的NA划分为同一组,在组内只填充前N个NA(N就是该组的locf_N):
library(data.table) library(zoo) test <- data.table( value = c(5,NA,8,NA,NA,8,6,NA,NA,10), locf_N = c(1,NA,1,NA,NA,1,2,NA,NA,2) ) # 给每个有效值及其可填充的NA标记分组 test[, group := cumsum(!is.na(value))] # 按组填充:组内行号<=允许次数+1时填充(+1是因为组第一个是有效值本身) test[, value := ifelse(.I - min(.I) <= locf_N[!is.na(value)][1], na.locf(value), NA), by = group] # 验证结果 test
两种方法都能得到你想要的输出:
value locf_N 1: 5 1 2: 5 NA 3: 8 1 4: 8 NA 5: NA NA 6: 8 1 7: 6 2 8: 6 NA 9: 6 NA 10: 10 2
简单来说,核心就是先把每个NA对应的“允许填充次数”找出来,再判断这个NA是否在可填充的范围内,最后决定是否用前一个有效值填充~
内容的提问来源于stack exchange,提问作者User981636
相关产品推荐
相关产品推荐

