如何基于date匹配,用另一DataFrame仅填充目标DataFrame的缺失值?
解决DataTable填充NA不覆盖非缺失值及批量处理的问题
嘿,我明白你的问题了——原来的写法会不小心覆盖掉df1里已经存在的非缺失值,而且逐列处理太麻烦对吧?咱们来一步步解决:
1. 先修正单列替换,避免覆盖非缺失值
你之前的代码之所以会替换掉第3行的val2,是因为data.table的直接赋值会把所有匹配到date的行都替换,不管原字段是不是NA。咱们用fifelse加个判断,只在原字段为NA的时候才替换:
library(data.table) setDT(df1) setDT(df2) # 仅替换val2列的NA值,保留非缺失值 df1[df2, val2 := fifelse(is.na(val2), i.val2, val2), on = .(date)]
这样处理后,df1第3行的val2就会保留原来的数值,不会被df2的值覆盖了。
2. 批量填充所有需要的列,不用逐列写代码
如果要一次性处理val2、val3这类多列,咱们可以先提取df2中除了date之外的列名,然后循环或者用lapply批量处理:
方法一:循环处理(直观易懂)
# 获取需要填充的列(df2中除date外的所有列) fill_columns <- setdiff(names(df2), "date") # 循环遍历每一列,执行NA替换逻辑 for (col in fill_columns) { df1[df2, (col) := fifelse(is.na(get(col)), get(paste0("i.", col)), get(col)), on = .(date)] }
方法二:用.SD和lapply(更简洁的data.table风格)
fill_columns <- setdiff(names(df2), "date") df1[df2, (fill_columns) := lapply(fill_columns, function(col) { fifelse(is.na(get(col)), get(paste0("i.", col)), get(col)) }), on = .(date)]
处理后的结果验证
执行完上面的代码后,df1会变成这样:
df1 date val1 val2 val3 1: 2001-01-01 -0.84085548 -0.6029080 -0.2857736 2: 2001-02-01 1.38435934 -0.4721664 0.1381082 3: 2001-03-01 -1.25549186 -0.6353713 1.2276303 4: 2001-04-01 0.07014277 -1.0803926 -0.1389861 5: 2001-05-01 1.71144087 -0.1575344 -0.5973131
可以看到:
- 第3行的非缺失值完好保留
- 第4、5行的NA被
df2对应日期的值成功替换
内容的提问来源于stack exchange,提问作者Gaurav Bansal
相关产品推荐
相关产品推荐

