如何在R中基于ID、EG与最邻近年份实现数据框左连接?
R中按ID、EG匹配并基于最邻近年份合并数据框的简便方案
需求说明
原本打算执行精确匹配的左连接:
merge(b, a, by=c("ID", "EG", "year"), all.x=TRUE)
但需要实现:当a中的年份在b中找不到时,将a的test值匹配到b中年份最接近的行(年份差相等时采用四舍五入规则),最终确保结果的所有行都能获取到对应最邻近年份的test值。
示例数据
set.seed(123) # 设置随机种子保证结果可复现 a <- data.frame(ID = 1:4, EG = c("CA", "EV", "EV", "TR"), year =c(2000, 2005, 2010, 2020), test = sample(4)) b <- data.frame(ID = 1:4, EG = c("CA", "EV", "EV", "TR"), test = sample(20), year = sample(2000:2019, 20, replace=TRUE))
方案一:使用dplyr + fuzzyjoin(直观易懂)
先安装并加载所需包:
install.packages(c("dplyr", "fuzzyjoin")) library(dplyr) library(fuzzyjoin)
执行匹配逻辑:
# 按ID、EG分组,计算b中每行与a中对应组各年份的差值,取最接近的 result <- fuzzy_left_join(b, a, by = c("ID", "EG", "year"), match_fun = list(`==`, `==`, function(x, y) TRUE)) %>% group_by(ID.x, EG.x, year.x, test.x) %>% mutate(year_diff = abs(year.x - year.y)) %>% filter(year_diff == min(year_diff)) %>% # 处理年份差相等的情况(四舍五入:选年份更大的那个) filter(year.y == max(year.y)) %>% ungroup() %>% select(ID = ID.x, EG = EG.x, year = year.x, test_b = test.x, test_a = test.y)
方案二:使用data.table(高效适合大数据)
先安装并加载data.table:
install.packages("data.table") library(data.table)
转换为data.table并执行滚动匹配:
setDT(a) setDT(b) # 按ID、EG分组,对year做滚动匹配,设置roll="nearest"实现最邻近匹配 result <- b[a, on = .(ID, EG, year), roll = "nearest", .(ID, EG, year = x.year, test_b = x.test, test_a = i.test)]
注:
roll="nearest"会自动处理年份差相等的情况,默认会选择较大的年份(符合四舍五入规则)。
内容的提问来源于stack exchange,提问作者Sulz
相关产品推荐
相关产品推荐

