如何用R data.table惯用方法补全id-name对中的缺失值
解决data.table中基于另一列填充NA的问题
这是个很典型的data.table填充NA的场景,你的问题核心是没搞清楚data.table链式操作中:=的作用对象——你之前的代码修改的是子集副本,不是原表!
为什么你的尝试没生效?
你写的代码:
id_name[is.na(name)][id_name[!is.na(name)], on="id", name:=i.name]
第一个[is.na(name)]会生成原表的临时子集(仅包含name为NA的行),后续的:=操作只会修改这个临时子集,根本没触碰到原表id_name,所以你查看原表时自然看不到变化。
正确的data.table惯用写法
我们需要直接在原表上做原地更新,借助data.table的连接和分组生成映射关系,再填充NA。步骤分为两步:先根据非NA的id填充name的NA,再根据非NA的name填充id的NA。
完整代码如下:
library(data.table) # 你的原始数据集 id_name = data.table(stringsAsFactors=FALSE, id = c("x123", "xy234","x123",NA,"z123","y123","d654","d654"), name = c("john", "mary", NA,"mary","bob","bob", "john",NA) ) # 步骤1:填充name列的NA(仅处理id非NA的行) id_name[is.na(name) & !is.na(id), name := id_name[!is.na(name), .(name = first(name)), by = id][.SD, on = "id", x.name]] # 步骤2:填充id列的NA(仅处理name非NA的行) id_name[is.na(id) & !is.na(name), id := id_name[!is.na(id), .(id = first(id)), by = name][.SD, on = "name", x.id]] # 查看最终结果 id_name
运行后会得到你预期的结果:
id name 1: x123 john 2: xy234 mary 3: x123 john 4: xy234 mary 5: z123 bob 6: y123 bob 7: d654 john 8: d654 john
代码关键逻辑解释
id_name[!is.na(name), .(name = first(name)), by = id]:按id分组,提取每个id对应的第一个非NAname,生成去重的id-name映射表。[.SD, on = "id", x.name]:将当前需要填充的子集(.SD,即name为NA且id非NA的行)和映射表按id连接,用映射表的name值填充NA。- 填充
id列的逻辑同理:按name分组生成name-id映射表,再填充对应NA。
如果遇到同一个id对应多个不同name(或同一个name对应多个不同id)的情况,你可以把first()换成last()或其他聚合函数,根据业务需求调整即可。
内容的提问来源于stack exchange,提问作者maximus
相关产品推荐
相关产品推荐

