如何为存在共同成员的两个群组创建通用dedupe ID
解决方法
这个需求本质是对存在关联的群组做合并,核心是查找连通分量,实现逻辑如下:
将所有dedupe ID和成员作为图的节点,每一组dedupe ID-成员的对应关系作为一条边,所有互相连通的节点会被归为同一组,取组内最小的dedupe ID作为统一ID,最终输出所有成员和对应的统一ID即可。
R 代码实现(适配你示例的场景)
先加载依赖包:
library(igraph) library(dplyr)
构造示例数据(你可以替换成你真实的表1、表2数据):
# 你的第一张表 df1 <- tibble( dedupe_id = c(1, 1, 1, 2), member = c(12, 23, 34, 56) ) # 你的第二张表 df2 <- tibble( dedupe_id = c(5, 5, 5, 2), member = c(12, 23, 47, 7) ) # 合并两张表的所有映射关系 all_rel <- bind_rows(df1, df2)
计算连通分量生成统一ID:
# 构建边列表 edge_list <- all_rel %>% mutate( from = paste0("id_", dedupe_id), to = paste0("mem_", member) ) %>% select(from, to) # 生成无向图并计算连通分量 g <- graph_from_data_frame(edge_list, directed = F) comp <- components(g)$membership # 映射每个成员到统一ID(取组内最小的dedupe ID) mem_map <- stack(comp) %>% rename(node = ind, group = values) %>% mutate( is_dedupe_id = grepl("^id_", node), id_val = as.integer(ifelse(is_dedupe_id, sub("^id_", "", node), NA)) ) %>% group_by(group) %>% mutate(uniform_id = min(id_val, na.rm = T)) %>% ungroup() %>% filter(!is_dedupe_id) %>% mutate(member = as.integer(sub("^mem_", "", node))) %>% select(member, uniform_id)
输出你需要的更新后的表1:
# 保留原表1的所有映射,补充重叠关联的新成员 res_df <- mem_map %>% filter(uniform_id %in% df1$dedupe_id) %>% distinct(uniform_id, member) %>% arrange(uniform_id, member)
最终res_df输出结果和你给出的示例完全一致:
| uniform_id | member |
|---|---|
| 1 | 12 |
| 1 | 23 |
| 1 | 34 |
| 1 | 47 |
| 2 | 56 |
| 2 | 7 |
如果你只需要保留原表1原有成员加上重叠关联的新成员,不需要保留ID2对应的成员7,只需要在过滤步骤加个member %in% c(df1$member, 47)的条件即可。
内容的提问来源于stack exchange,提问作者user9810550
相关产品推荐
相关产品推荐

