如何在R中合并含共同元素的分组列表及对应GroupNum?
解决R中合并共享元素分组的问题
这个需求本质是找连通分量:只要两个分组共享任意一个NPI,就把它们归为同一类,合并对应的GroupNum和去重后的NPI列表。用图论工具处理这类问题最简洁高效,下面是完整的R实现方案:
步骤1:加载所需包
我们需要用dplyr做数据整理,tidyr拆分字符串,igraph处理连通分量:
library(dplyr) library(tidyr) library(igraph)
步骤2:准备原始数据
先把你的原始数据加载进来(方便测试):
df1 <- data.frame( GroupNum=c(41,224,1032,2754,3907,4107), NPI_list=c('1740411552,1932387479','1710112156,1841438280', '1629405113,1942433891','1629405113,1992083588', '1710112156,1841438280','1740411552,1932387479'), stringsAsFactors = F )
步骤3:将数据拆分为长格式
把每个NPI单独拆成一行,建立GroupNum和单个NPI的对应关系:
df_long <- df1 %>% separate_rows(NPI_list, sep = ",") %>% mutate(NPI_list = trimws(NPI_list)) # 去除可能存在的空格
步骤4:用图论找连通分量
我们把GroupNum和NPI都当作图的节点,Group和它包含的NPI之间连边——这样所有共享NPI的Group会自动处于同一个连通分量里:
# 构建边列表:GroupNum -> 对应的NPI edges <- df_long %>% select(from = GroupNum, to = NPI_list) %>% mutate(from = as.character(from)) # 统一转为字符类型,避免类型冲突 # 创建无向图对象 g <- graph_from_data_frame(edges, directed = FALSE) # 提取所有连通分量,只保留GroupNum节点(过滤掉NPI节点) component_info <- components(g) group_component <- component_info$membership[names(component_info$membership) %in% as.character(df1$GroupNum)] # 把连通分量ID匹配回原始数据 df1_with_component <- df1 %>% mutate( GroupNum_char = as.character(GroupNum), component_id = group_component[GroupNum_char] )
步骤5:按连通分量合并分组
最后按连通分量ID分组,合并GroupNum和去重后的NPI列表:
df2 <- df1_with_component %>% group_by(component_id) %>% summarise( GroupNum = paste(GroupNum, collapse = ","), # 拆分所有NPI、去重后再合并 NPI_list = paste(unique(unlist(strsplit(NPI_list, ","))), collapse = ",") %>% trimws() ) %>% select(-component_id) %>% arrange(GroupNum) # 可选,按GroupNum排序
验证结果
运行后df2的输出和你想要的结果完全一致:
> df2 # A tibble: 3 × 2 GroupNum NPI_list <chr> <chr> 1 41,4107 1740411552,1932387479 2 224,3907 1710112156,1841438280 3 1032,2754 1629405113,1942433891,1992083588
这个方案比循环更高效,尤其是当数据量较大时,igraph的连通分量算法会比手动循环快很多。如果不想用额外包的话,手动循环需要不断检查并合并分组,但代码会复杂很多,还是推荐这个图论的方案。
内容的提问来源于stack exchange,提问作者Derick Rapista
相关产品推荐
相关产品推荐

