如何在R数据集内按特定规则创建关联匹配行的新变量var7
R语言:按规则匹配分组并填充var7列
原始数据集
df <- data.frame(var1 = rep(LETTERS[1:3], each = 4), var2 = rep(LETTERS[4:6], each = 2), var3 = c('F', 'F', 'F', 'F', 'G', 'G'), var4 = c('H', 'H', 'I', 'I', 'L', 'L'), var5 = c('M', 'N', 'O', 'N', 'M', 'P', 'M', 'N', 'O', 'N', 'M', 'N'), var6 = c('x', 'y', 'x', 'y', 'x', 'y'), var7 = c('', '', '', '', '', ''))
匹配填充规则
- 按
var1、var2、var3、var4分组,组内对比行对:若两行的var5和var6均不同,则视为匹配,为这两行分配相同的唯一var7值建立关联。 - 若某一行存在多个匹配项(如与两个
var5不同的行匹配),则复制该行,为每个复制行及对应匹配行分配唯一var7值。 - 若两行的分组字段(
var1/var2/var3/var4)不同,或var6相同,则不匹配,不操作。
期望结果
df2 <- data.frame(var1 = rep(LETTERS[1:3], each = 4), var2 = rep(LETTERS[4:6], each = 2), var3 = c('F', 'F', 'F', 'F', 'G', 'G'), var4 = c('H', 'H', 'I', 'I', 'L', 'L'), var5 = c('M', 'N', 'O', 'N', 'M', 'P', 'M', 'N', 'O', 'N', 'M', 'N'), var6 = c('x', 'y', 'x', 'y', 'x', 'y'), var7 = c('1', '1', '2', '2', '3', '3', '4', '4', '5', '5', '6', '6'))
解决方案
结合dplyr和tidyr实现,核心逻辑是先分组匹配,再处理多匹配的复制行,最后映射唯一ID:
library(dplyr) library(tidyr) library(purrr) result <- df %>% # 按指定字段分组 group_by(var1, var2, var3, var4) %>% # 为每行找出所有符合条件的匹配行索引 mutate(row_num = row_number(), matches = map(row_num, ~{ current <- cur_data()[.x,] filter(cur_data(), var6 != current$var6, var5 != current$var5) %>% pull(row_num) })) %>% # 拆分多匹配情况,自动复制行 unnest(matches, keep_empty = FALSE) %>% # 避免同一匹配对重复处理 filter(row_num < matches) %>% # 生成唯一匹配ID mutate(var7 = as.character(row_number())) %>% # 关联回原数据,把ID映射到匹配的两行 right_join(df %>% mutate(row_num = row_number()), by = c("var1", "var2", "var3", "var4", "var5", "var6", "row_num")) %>% left_join(select(., matches, var7), by = c("row_num" = "matches"), suffix = c("", "_match")) %>% # 统一填充var7值 mutate(var7 = coalesce(var7, var7_match)) %>% # 整理格式,恢复原数据顺序 select(-matches, -row_num, -var7_match) %>% arrange(match(var1, LETTERS[1:3]), match(var2, LETTERS[4:6]), var3, var4, var5, var6)
关键逻辑说明
- 分组后用
map遍历每行,精准筛选符合var6不同+var5不同的匹配行; - 多匹配时通过
unnest自动拆分复制行,满足一对多的匹配需求; - 用
row_num < matches过滤重复匹配对,避免同一组内的行对被重复赋值; - 两次关联操作把唯一ID同步到匹配的两行,确保关联关系正确。
内容的提问来源于stack exchange,提问作者Lorenzo
相关产品推荐
相关产品推荐

