R中分组数据匹配生成other_id变量的实现问题
问题:R中基于分组数据匹配并记录对应行的id
数据集结构
df <- data.frame( id = c(1,1,2,2,3,3,4,5), group = c('A','A','A','A','A','A','B','B'), value1 = c('m', 'm', 'f', 'm', 'f', 'm', 'f', 'm'), value2 = c(50, 50, 20, 50, 20, 50, 60, 20), value1_1 = c('f', 'f', 'm', 'm', 'm', 'm', 'm', 'f'), value2_1 = c(20, 20, 50, 50, 50, 50, 20, 60) )
需求
在每个group内,判断当前行的value1等于组内其他行的value1_1,且当前行的value2等于组内其他行的value2_1;若满足条件,新建变量other_id记录匹配行的id(多个匹配用逗号分隔),否则为NA。
当前代码的问题
现有代码如下:
df <- df %>% group_by(group) %>% mutate(other_id = ifelse(value1 %in% value1_1 & value2 %in% value2_1, id, NA)) %>% ungroup()
存在两个问题:
- 会匹配到当前行自身,不符合“其他行”的要求
other_id记录的是当前行的id,而非匹配行的id
期望输出
df <- data.frame( id = c(1,1,2,2,3,3,4,5), group = c('A','A','A','A','A','A','B','B'), value1 = c('m', 'm', 'f', 'm', 'f', 'm', 'f', 'm'), value2 = c(50, 50, 20, 50, 20, 50, 60, 20), value1_1 = c('f', 'f', 'm', 'm', 'm', 'm', 'm', 'f'), value2_1 = c(20, 20, 50, 50, 50, 50, 20, 60), other_id = c("2,3", "2,3", "1", "3", "1", "2", "5", "4"))
解决方案
可以通过分组内的自连接实现需求,具体代码如下:
library(dplyr) library(tidyr) # 给原数据添加行号,用于精准区分自身行 df <- df %>% mutate(row_num = row_number()) # 分组内自连接,筛选匹配且非自身的行,合并匹配id matched_df <- df %>% group_by(group) %>% inner_join(df, by = c("group", "value1" = "value1_1", "value2" = "value2_1"), suffix = c("", "_match")) %>% filter(row_num != row_num_match) %>% group_by(row_num) %>% summarise(other_id = paste(unique(id_match), collapse = ",")) %>% ungroup() # 将匹配结果合并回原数据,未匹配项填充NA df_final <- df %>% left_join(matched_df, by = "row_num") %>% select(-row_num) # 查看最终结果 print(df_final)
代码说明
- 添加
row_num是为了避免匹配到当前行,即使同一id对应多行也能准确区分 inner_join筛选出满足value1=value1_1且value2=value2_1的行,filter剔除自身匹配summarise结合paste将同一行的多个匹配id合并为逗号分隔的字符串left_join将匹配结果合并回原数据,未匹配的行other_id自动填充为NA
运行后得到的结果与期望输出完全一致。
内容的提问来源于stack exchange,提问作者kris
相关产品推荐
相关产品推荐

