合并两个data.table时,如何用dt2值替换dt1子键列的NA?
解决data.table合并时用非NA值替换子键列NA的问题
我明白你的需求了——你希望在合并两个data.table时,当dt1里的子键列(比如示例中的number)出现NA时,自动用dt2对应行的有效值来替换它,而不是保留原来的NA。默认的多key合并做不到这一点,因为NA在匹配时不会和任何值(包括另一个NA)相等,所以得换个思路来处理。
先规整你的示例数据(方便测试)
library(data.table) dt1 <- data.table( letter = c("a", "b", "c", "d"), number = c(10, NA, 30, 40), size = c("big", "small", "big", "big") ) dt2 <- data.table( letter = c("a", "b", "c", "d"), number = c(10, 20, 30, 40), color = c("blue", "orange", "yellow", "red") )
解决方案:先按主键合并,再用fcoalesce填充NA
核心思路是:先基于唯一能确定匹配关系的主键(这里是letter)合并,确保同一主键的行都能对应上;再对需要填充的子键列,用data.table的fcoalesce函数取两个表中该列的第一个非NA值——这样dt1有有效值时保留,dt1是NA时就用dt2的值。
具体代码如下:
# 设置主键为唯一确定匹配的letter setkey(dt1, letter) setkey(dt2, letter) # 合并后处理子键列和其他字段 dt_merged <- merge(dt1, dt2, by = "letter", all = TRUE)[ , `:=`( # 优先用dt1的number,NA则取dt2的number number = fcoalesce(number.x, number.y), # 如果size只有dt1有,这步可以省略;如果dt2也有size列,同样可以用fcoalesce处理 size = fcoalesce(size, NA), # color只有dt2有,直接保留即可,这里写出来是示例多字段处理逻辑 color = fcoalesce(color, NA) ) ][, c("number.x", "number.y") := NULL] # 删除合并产生的临时列 # 查看最终结果 dt_merged
运行后得到的结果正是你想要的:
letter number size color 1: a 10 big blue 2: b 20 small orange 3: c 30 big yellow 4: d 40 big red
批量处理多个子键列的情况
如果你有多个子键列(比如col2、col3、col4都需要替换NA),可以用批量处理的方式,不用一个个写:
# 定义需要处理的子键列 sub_key_cols <- c("col2", "col3", "col4") # 按主键合并 dt_merged <- merge(dt1, dt2, by = "col1", all = TRUE) # 批量处理每个子键列 dt_merged[, (sub_key_cols) := lapply(sub_key_cols, function(col) { fcoalesce(get(paste0(col, ".x")), get(paste0(col, ".y"))) })] # 删除所有临时列 dt_merged[, paste0(sub_key_cols, c(".x", ".y")) := NULL]
为什么原来的方法不行?
你之前用setkey(dt1, letter, number)和setkey(dt2, letter, number)后合并,由于R中NA == 任何值的结果都是NA,所以dt1中letter=b, number=NA的行,和dt2中letter=b, number=20的行会被判定为不匹配。加上all=TRUE后,合并时会把这两行的非NA字段拼在一起,但子键列的NA不会自动替换——这就是你遇到的问题。
内容的提问来源于stack exchange,提问作者Aarón Gzz
相关产品推荐
相关产品推荐

