如何基于行内不同列匹配合并R中的两个Data.Frame
问题描述
我有如下两个R数据框:
Df1:
Df1 <- data.frame( ID = c(101, 102, 103, 104, 105), ID_T1 = c(NA, 11111, 22222, NA, 44444), ID_T2 = c(NA, 11111, 22222, NA, 44445), ID_T3 = c(NA, 11111, NA, NA, NA), ID_T4 = c(NA, 11111, NA, NA, NA) )
注:包含NA值,且部分行的ID值存在差异。
Df2(或可视为向量):
Df2 <- data.frame(ID_T5 = c(44445, 11111, 22222, 99945))
注:包含新分配的ID值。
我需要得到如下输出结果:
ID ID_T1 ID_T2 ID_T3 ID_T4 ID_T5 1 101 NA NA NA NA NA 2 102 11111 11111 11111 11111 11111 3 103 22222 22222 NA NA 22222 4 104 NA NA NA NA NA 5 105 44444 44445 NA NA 44445 6 NA NA NA NA NA 99945
需求说明:检查Df1的ID_T1至ID_T4列,若Df2中的ID已存在则添加为ID_T5列值;若ID未在Df1中出现,则新增对应行。
我尝试用dplyr的filter和mutate函数但没成功,求帮助。
解决方案
结合dplyr和tidyr工具可以实现需求,具体步骤如下:
- 给Df1添加初始的
ID_T5列,默认值为NA - 匹配Df1每行中存在的非NA的
ID_T1-ID_T4值,将Df2中对应的ID填充到该行的ID_T5 - 筛选出Df2中未出现在Df1任何
ID_T1-ID_T4列的ID,新增对应行到结果中
完整代码:
library(dplyr) library(tidyr) # 初始化结果数据框,添加ID_T5列 result <- Df1 %>% mutate(ID_T5 = NA_integer_) # 匹配已存在的ID,填充ID_T5 matched_ids <- result %>% pivot_longer(cols = starts_with("ID_T"), names_to = "type", values_to = "value") %>% filter(!is.na(value)) %>% inner_join(Df2, by = c("value" = "ID_T5")) %>% distinct(ID, value) %>% rename(ID_T5 = value) result <- result %>% left_join(matched_ids, by = "ID") %>% mutate(ID_T5 = coalesce(ID_T5.y, ID_T5.x)) %>% select(-ID_T5.x, -ID_T5.y) # 处理未匹配的ID,新增行 unmatched_ids <- Df2 %>% filter(!ID_T5 %in% unlist(Df1[, starts_with("ID_T")], use.names = FALSE)) %>% mutate(ID = NA, ID_T1 = NA, ID_T2 = NA, ID_T3 = NA, ID_T4 = NA) %>% select(ID, ID_T1, ID_T2, ID_T3, ID_T4, ID_T5) # 合并最终结果 result <- bind_rows(result, unmatched_ids) # 输出结果 print(result)
内容的提问来源于stack exchange,提问作者kuli
相关产品推荐
相关产品推荐

