R语言基于UserID匹配与日差≤30的两个DataFrame模糊合并实现问题
适配需求的合并实现方案
方案1:使用powerjoin包实现模糊全连接(推荐,语法简洁符合dplyr使用习惯)
powerjoin是专门扩展dplyr连接功能的包,原生支持自定义条件的模糊连接,直接适配你的需求:
首先安装加载依赖:
install.packages("powerjoin") library(powerjoin) library(lubridate)
然后执行全连接:
# 执行按规则的全连接 merge_res <- power_full_join( df11, df22, # 第一匹配条件:UserID相等 by = "UserID", # 第二匹配条件:日期差值≤30天 condition = ~ abs(as.duration(.x$Date %--% .y$EncounterDate)) / ddays(1) <= 30, # 重名列自动加后缀区分 suffix = c("_df1", "_df2") )
这个方法会自动保留所有df11和df22的行,满足条件的行合并为单行,不满足匹配条件的行对应另一表的列填充NA。
方案2:使用sqldf包通过SQL语法实现
如果你更习惯SQL操作,可以用这个方案:
安装加载依赖:
install.packages("sqldf") library(sqldf)
执行全连接(SQLite不直接支持全外连接,通过左连接+右连接去重实现):
merge_res <- sqldf(" -- 左连接保留所有df11的行 SELECT a.*, b.* FROM df11 a LEFT JOIN df22 b ON a.UserID = b.UserID AND abs(julianday(a.Date) - julianday(b.EncounterDate)) <=30 UNION -- 右连接保留所有df22的行 SELECT a.*, b.* FROM df11 a RIGHT JOIN df22 b ON a.UserID = b.UserID AND abs(julianday(a.Date) - julianday(b.EncounterDate)) <=30 ")
两种方案输出结果一致,符合你要求的匹配规则:比如你的数据中UserID=1的2021-01-02行可以匹配到df22中UserID=1的2021-01-01行,UserID=1的2021-12-11行没有符合日期条件的匹配,对应df22的列会填充NA,仅在df11中存在的UserID=7行,对应df22列也填充NA。
内容的提问来源于stack exchange,提问作者Ash S
相关产品推荐
相关产品推荐

