R语言中基于ID匹配实现指定列求和并保留无匹配ID的行
R语言中基于ID匹配实现指定列求和并保留无匹配ID的行
我懂你的需求啦——要把两个数据集里对应公司ID的员工存量(2014年底的stock)和2015年净招聘流量(flow)加起来,还得保留所有原long数据集里的公司,哪怕有些公司在short里没有2015年的招聘数据对吧?之前用rbindlist加按ID求和的方法没踩准需求,还丢了无匹配的行,我来给你调整下正确的方案~
先模拟你的数据集(方便理解和测试)
先造两个和你描述一致的小数据集,方便后续演示:
library(data.table) # 模拟long数据集:2014年底员工存量 long <- data.table(ID = c(1,2,3,4), stock = c(100, 200, 150, 300)) # 模拟short数据集:2015年净招聘流量(只有ID1和ID3有数据) short <- data.table(ID = c(1,3), flow = c(10, -5))
问题出在哪?
你之前用rbindlist合并后按ID求和的逻辑,本质是把两个数据集的行堆叠后,对每列分别按ID求和——这不是你要的“存量+流量”的对应行相加逻辑,而且虽然sum(na.rm=T)会把NA当0,但这种方式容易混淆列求和与行内计算,最终导致结果不符合预期。
正确方案:左连接 + 补0 + 行内求和
核心思路是用左连接强制保留long里的所有ID,把short中的flow匹配到对应ID上,没有匹配到的flow设为0(因为没有净招聘就是变化量为0),再计算新的员工数:
用data.table实现(和你原代码的工具一致)
# 1. 左连接:保留long的所有ID,匹配short的flow列 data_new <- long[short, on = .(ID), flow := i.flow] # 2. 把未匹配到的flow(NA)替换为0 data_new[is.na(flow), flow := 0] # 3. 计算2015年底的员工数 data_new[, stock_2015 := stock + flow]
运行后你会得到符合预期的完整结果:
| ID | stock | flow | stock_2015 |
|---|---|---|---|
| 1 | 100 | 10 | 110 |
| 2 | 200 | 0 | 200 |
| 3 | 150 | -5 | 145 |
| 4 | 300 | 0 | 300 |
更简洁的合并写法
可以把步骤合并成一行,代码更紧凑:
data_new <- long[short, on = .(ID), .(ID, stock, flow = i.flow)][ is.na(flow), flow := 0][, stock_2015 := stock + flow]
如果你习惯用dplyr的话
也可以用dplyr的左连接实现,逻辑完全一致:
library(dplyr) data_new <- long %>% left_join(short, by = "ID") %>% mutate(flow = replace_na(flow, 0), stock_2015 = stock + flow)
这样就能完美保留所有原long里的ID,同时完成对应行的存量加流量计算啦~
备注:内容来源于stack exchange,提问作者Maximilian
相关产品推荐
相关产品推荐

