基于Name列匹配实现两个R DataFrame按行数值相减
在R语言中基于Name列匹配实现多数值列批量相减并保留指定列
问题说明
需基于Name列的字符串匹配,将业务数据DF1的所有数值列减去参考数据DF2中同Name行的对应数值列,最终保留DF1的Name和Key列生成目标数据框DF3,且要支持任意数量数值列的通用处理,无需硬编码列名。
示例数据
# 业务数据DF1 Name <- c("X_1_group1", "X_2_group1", "X_2_group2", "X_2_group1", "X1_group2") Key <- c("test1234", "test4553", "test3341", "test2142", "test4722") BCD12A <- c(10, 8, 5, 5, 6) ACA1 <- c(10, 7, 5, 6, 7) DEX2 <- c(8, 4, 5, 8, 4) DF1 <- data.frame(Name, Key, BCD12A, ACA1, DEX2) # 参考数据DF2 Name <- c("X_1_group1", "X_2_group1", "X_1_group2", "X_2_group2") Key <- c("X_1_group1_A", "X_1_group1_B", "X_1_group1_C", "X_1_group1_D") BCD12A <- c(2, 1, 2, 2) ACA1 <- c(2, 3, 2, 1) DEX2 <- c(1, 1, 3, 2) DF2 <- data.frame(Name, Key, BCD12A, ACA1, DEX2)
通用解决方案(支持任意数值列)
使用dplyr和tidyr包实现自动识别数值列、批量计算的功能:
library(dplyr) # 1. 自动提取两个数据框中共同的数值列(排除Name、Key) num_cols <- intersect(setdiff(colnames(DF1), c("Name", "Key")), setdiff(colnames(DF2), c("Name", "Key"))) # 2. 处理DF2:仅保留用于匹配的Name和数值列 DF2_clean <- DF2 %>% select(Name, all_of(num_cols)) # 3. 左连接+批量计算差值 DF3 <- DF1 %>% left_join(DF2_clean, by = "Name", suffix = c("_df1", "_df2")) %>% # 对每个数值列执行 DF1值 - DF2值 的计算 mutate(across(all_of(num_cols), ~ .data[[paste0(cur_column(), "_df1")]] - .data[[paste0(cur_column(), "_df2")]])) %>% # 保留DF1的Name、Key和计算后的数值列 select(Name, Key, all_of(num_cols)) # 查看结果 print(DF3)
额外说明
- 若DF1中存在DF2无匹配的
Name(如示例中的X1_group2),对应数值列会返回NA;若需将NA替换为0,可在mutate后添加replace_na(setNames(rep(0, length(num_cols)), num_cols)) - 代码无需修改列名即可适配新增的数值列,完全满足通用场景需求
内容的提问来源于stack exchange,提问作者dkcongo
相关产品推荐
相关产品推荐

