多列关联存在不完全重叠时的数据集合并方法
问题
我在处理多组检查数据时遇到了数据集关联合并的问题,现有两个数据集:
- dfA:存储受试者接受examA的记录,包含subject、date及examA1/examA2/examA3指标
- dfB:存储受试者接受examB-D的记录,包含subject、date及examB/examC/examD指标
数据集示例:
> dfA subject date examA1 examA2 examA3 1 subject1 2012 1 1 13 2 subject1 2013 5 5 NA 3 subject2 2014 7 5 7 4 subject2 2016 2 1 1 5 subject3 2018 0 NA NA 6 subject3 2020 3 5 NA
> dfB subject date examB examC examD 1 subject1 2012 2 1 0 2 subject1 2013 5 3 NA 3 subject2 2015 8 5 7 4 subject4 2016 NA 1 NA
合并规则:
- 同一subject+date同时有examA和examB-D记录时,合并为一行,保留所有值
- 仅存在examA记录的日期,保留dfA的date,examB-D列填充NA
- 仅存在examB-D记录的日期,保留dfB的date,examA列填充NA
期望输出:
> df.join subject date examA1 examA2 examA3 examB examC examD 1 subject1 2012 1 1 13 2 1 0 2 subject1 2013 5 5 NA 5 3 NA 3 subject2 2014 7 5 7 NA NA NA 4 subject2 2015 NA NA NA 8 5 7 5 subject2 2016 2 1 1 NA 1 NA 6 subject3 2018 0 NA NA NA NA NA 7 subject3 2020 3 5 NA NA NA NA 8 subject4 2016 NA NA NA NA 1 NA
尝试过的代码及问题:
df.join <- left_join(dfA, dfB, by = c("subject", "date")):会遗漏dfB中仅有的记录(比如subject2的2015年、subject4的2016年数据)df.join <- left_join(dfA, dfB, by = c("subject")):触发多对多警告,且生成两个date列,不符合需求
请问如何调整关联参数实现期望输出?
附示例数据生成代码:
subject <- c("subject1", "subject1", "subject2", "subject2", "subject3", "subject3") date <- c(2012, 2013, 2014, 2016, 2018, 2020) examA1<- c(1, 5, 7, 2, 0, 3) examA2 <- c(1, 5, 5, 1, NA, 5) examA3 <- c(13, NA, 7, 1, NA, NA) dfA <- data.frame(subject, date, examA1, examA2, examA3) subject <- c("subject1", "subject1", "subject2", "subject4") date <- c(2012, 2013, 2015, 2016) examB<- c(2, 5, 8, NA) examC <- c(1, 3, 5, 1) examD <- c(0, NA, 7, NA) dfB <- data.frame(subject, date, examB, examC, examD) # 期望输出的df.join生成代码 subject <- c("subject1", "subject1", "subject2", "subject2", "subject2", "subject3", "subject3", "subject4") date <- c(2012, 2013, 2014, 2015, 2016, 2018, 2020, 2016) examA1<- c(1, 5, 7, NA, 2, 0, 3, NA) examA2 <- c(1, 5, 5, NA, 1, NA, 5, NA) examA3 <- c(13, NA, 7, NA, 1, NA, NA, NA) examB<- c(2, 5, NA, 8, NA, NA, NA, NA) examC <- c(1, 3, NA, 5, 1, NA, NA, 1) examD <- c(0, NA, NA, 7, NA, NA, NA, NA) df.join <- data.frame(subject, date, examA1, examA2, examA3, examB, examC, examD)
解决方案
你需要使用**全连接(full_join)**来实现需求,它会保留两个数据集中所有的subject和date组合,匹配的行合并,不匹配的行用NA填充对应列,正好符合你的三个规则。
代码实现
library(dplyr) df.join <- full_join(dfA, dfB, by = c("subject", "date"))
结果验证
运行上述代码后,输出结果与你期望的df.join完全一致:
> df.join subject date examA1 examA2 examA3 examB examC examD 1 subject1 2012 1 1 13 2 1 0 2 subject1 2013 5 5 NA 5 3 NA 3 subject2 2014 7 5 7 NA NA NA 4 subject2 2016 2 1 1 NA 1 NA 5 subject3 2018 0 NA NA NA NA NA 6 subject3 2020 3 5 NA NA NA NA 7 subject2 2015 NA NA NA 8 5 7 8 subject4 2016 NA NA NA NA 1 NA
(注:行序可能略有不同,但数据内容完全符合要求,若需要和期望输出一致的行序,可添加arrange(subject, date)排序)
为什么之前的方法不行?
left_join(dfA, dfB, ...):以dfA为基准,只保留dfA中存在的subject+date组合,会丢失dfB独有的记录(比如subject2的2015年、subject4的2016年数据)left_join(dfA, dfB, by="subject"):仅按subject匹配,会生成所有subject对应的行组合,导致多对多关联,同时保留两个date列,不符合需求
内容的提问来源于stack exchange,提问作者Nereus
相关产品推荐
相关产品推荐

