在R中对比行列不同的两个data.frame,提取相同数据至df3差异至df4
解决方案
针对你需要对比行列数不同的data.frame并拆分完全相同/差异数据的需求,这里提供几种简洁的实现方式,基于dplyr包完成:
方式一:提取所有列完全相同的行
这种方式严格匹配列名和对应数值均完全一致的行存入df3,其余所有行(包括仅单表存在、列数差异导致的不匹配、数值差异的行)存入df4。
# 加载dplyr(未安装则先运行 install.packages("dplyr")) library(dplyr) set.seed(22) df1 <- data.frame(id=sample(LETTERS, 9, FALSE), col1=sample(0:2, 9, TRUE), col2 = sample(0:2, 9, TRUE)) df2 <- data.frame(id=sample(LETTERS, 17, FALSE), col1=sample(0:2, 17, TRUE), col2 = sample(0:2, 17, TRUE), col6 = sample(0:2, 17, TRUE)) # 获取两个表的所有列名,补全缺失列并填充NA all_cols <- union(names(df1), names(df2)) df1_full <- df1 %>% mutate(across(setdiff(all_cols, names(.)), ~NA)) %>% select(all_cols) df2_full <- df2 %>% mutate(across(setdiff(all_cols, names(.)), ~NA)) %>% select(all_cols) # 提取完全相同的行 df3 <- inner_join(df1_full, df2_full, by = all_cols) %>% distinct() # 提取所有差异行 df4 <- bind_rows(anti_join(df1_full, df3, by = all_cols), anti_join(df2_full, df3, by = all_cols))
方式二:提取共同列完全匹配的行
如果你的需求是将id相同且共同列(id、col1、col2)数值完全一致的行存入df3,其余数据(含仅单表存在的行、共同列数值差异的行、共同列匹配但额外列差异的行)存入df4,用以下代码:
library(dplyr) set.seed(22) df1 <- data.frame(id=sample(LETTERS, 9, FALSE), col1=sample(0:2, 9, TRUE), col2 = sample(0:2, 9, TRUE)) df2 <- data.frame(id=sample(LETTERS, 17, FALSE), col1=sample(0:2, 17, TRUE), col2 = sample(0:2, 17, TRUE), col6 = sample(0:2, 17, TRUE)) # 获取共同列名 common_cols <- intersect(names(df1), names(df2)) # 找出共同列完全匹配的行 matched_rows <- inner_join(df1, df2, by = common_cols) %>% select(all_of(common_cols)) %>% distinct() df3 <- matched_rows # 整理所有差异数据 df4 <- bind_rows( # df1中非匹配的行 anti_join(df1, matched_rows, by = common_cols), # df2中非匹配的行 anti_join(df2, matched_rows, by = common_cols), # df2中匹配行的额外列数据(因df1无这些列,属于差异部分) inner_join(matched_rows, df2, by = common_cols) %>% select(id, col6) )
带来源标记的差异拆分
如果需要更清晰的差异标记(比如区分数据来自哪个表),可以用全连接方式:
library(dplyr) set.seed(22) df1 <- data.frame(id=sample(LETTERS, 9, FALSE), col1=sample(0:2, 9, TRUE), col2 = sample(0:2, 9, TRUE)) df2 <- data.frame(id=sample(LETTERS, 17, FALSE), col1=sample(0:2, 17, TRUE), col2 = sample(0:2, 17, TRUE), col6 = sample(0:2, 17, TRUE)) common_cols <- intersect(names(df1), names(df2)) # 全连接并标记来源 df_combined <- full_join( df1 %>% mutate(source = "df1"), df2 %>% mutate(source = "df2"), by = common_cols, suffix = c("_df1", "_df2") ) # 标记是否共同列匹配 df_combined <- df_combined %>% mutate(is_matched = ifelse(!is.na(id) & col1 == col1_df2 & col2 == col2_df2, TRUE, FALSE)) # 拆分df3和df4 df3 <- df_combined %>% filter(is_matched) %>% select(all_of(common_cols)) %>% distinct() df4 <- df_combined %>% filter(!is_matched | is.na(is_matched)) %>% select(-is_matched)
内容的提问来源于stack exchange,提问作者Ollie
相关产品推荐
相关产品推荐

