R语言中按行逐列匹配数据框成对列并新增匹配值列
动态匹配成对列并新增对应值的R语言解决方案
数据定义
df1 <- data.frame( col1 = c(1, 2, 3), col2 = c(4, 5, 6), col3 = c(2, 8, 9), col4 = c(5, 11, 12), col5 = c(13, 14, 15), col6 = c(16, 17, 18), col7 = c(19, 20, 21), col8 = c(22, 23, 24) ) df2 <- data.frame( colA = c(1, 2, 3), colB = c(4, 5, 6), value = c(100, 200, 300) )
需求说明
需要在df1中按行从左到右遍历所有成对列(如col1&col2、col3&col4……),每一对与df2的colA、colB进行匹配,匹配成功则新增一列存储df2对应的value值,最终得到包含原数据和所有匹配结果的df3(示例结构如下):
df3 <- data.frame( col1 = c(1, 2, 3), col2 = c(4, 5, 6), col3 = c(2, 8, 9), col4 = c(5, 11, 12), col5 = c(13, 14, 15), col6 = c(16, 17, 18), col7 = c(19, 20, 21), col8 = c(22, 23, 24), match1 = c(100, 200, 300), match2 = c(200, NA, NA) )
现有尝试及问题
之前尝试的代码只能处理一组列的匹配,无法适配df1列数动态变化的场景:
df_match <- inner_join(df1, df2, by = c("col1" = "colA", "col2" = "colB")) df1$matched_value <- df_match$value[match(paste(df1$col1, df1$col2), paste(df_match$col1, df_match$col2))]
动态列数的解决方案
可以通过成对遍历df1的列,逐一对每列组合进行匹配,最后将结果合并回原数据框。以下是两种实现方式:
方式1:基础R循环实现
# 确定成对列的组数(需确保df1列数为偶数) pair_count <- ncol(df1) %/% 2 # 初始化结果为原df1 df3 <- df1 # 循环处理每一对列 for(i in 1:pair_count) { # 获取当前成对的列名 col1_name <- paste0("col", (i*2)-1) col2_name <- paste0("col", i*2) # 生成匹配键,与df2的colA、colB匹配 match_key <- paste(df3[[col1_name]], df3[[col2_name]]) df2_key <- paste(df2$colA, df2$colB) # 匹配并新增列 df3[[paste0("match", i)]] <- df2$value[match(match_key, df2_key)] }
方式2:tidyverse + purrr实现
如果习惯用tidyverse工具链,可通过分组映射来处理:
library(tidyverse) # 将df1转换为长格式,按行和列组分组 df1_long <- df1 %>% mutate(row_id = row_number()) %>% pivot_longer(-row_id, names_to = "col", values_to = "val") %>% mutate(pair_group = ceiling(as.integer(str_remove(col, "col"))/2)) %>% pivot_wider(names_from = col, values_from = val) %>% rename_with(~c("row_id", "pair_group", "colA", "colB"), 1:4) # 与df2匹配后再转宽格式合并回原数据 match_results <- df1_long %>% left_join(df2, by = c("colA", "colB")) %>% select(row_id, pair_group, value) %>% pivot_wider(names_from = pair_group, values_from = value, names_prefix = "match") # 合并原数据和匹配结果 df3 <- df1 %>% mutate(row_id = row_number()) %>% left_join(match_results, by = "row_id") %>% select(-row_id)
两种方式都能自动适配df1的动态列数(只要列数为偶数),最终生成符合要求的df3。
内容的提问来源于stack exchange,提问作者Hard_Course
相关产品推荐
相关产品推荐

