如何在tibble中识别跨行关联的数值并进行分组
解决方案:用图论找连通分量
这种递归关联的分组本质是找无向图的连通分量——把每个数值看作节点,两列的每一行看作节点间的一条边,属于同一连通分量的节点就是同一分组。用igraph包可以高效实现,比多次自连接简洁且性能更优,尤其适合大型数据集。
实现步骤
- 把原数据的两列转换为无向边列表,构建图对象
- 提取图的连通分量,得到每个节点的分组编号
- 整理成目标格式输出
完整代码
library(tidyverse) library(igraph) # 原数据 test <- structure(list(one = c(5014, 5014, 5014, 5033, 5033, 5033, 5040, 5040, 5040, 5171, 5171, 5171, 5174, 5174, 5174, 5183, 5183, 5183, 5193, 5193, 5193, 5304, 5304, 5304), two = c(5033, 5040, 5304, 5014, 5040, 5304, 5014, 5033, 5304, 5174, 5183, 5331, 5171, 5183, 5331, 5171, 5174, 5331, 5161, 1538, 5190, 5014, 5033, 5040)), row.names = c(NA, -24L), class = c("tbl_df", "tbl", "data.frame")) # 构建无向图 graph <- graph_from_data_frame(test, directed = FALSE) # 获取连通分量分组信息 component_result <- components(graph) group_data <- tibble( 数值 = as.integer(names(component_result$membership)), 分组编号 = component_result$membership ) # 整理成目标格式并排序 final_result <- group_data %>% arrange(分组编号, 数值) print(final_result)
代码说明
graph_from_data_frame(test, directed = FALSE):将原数据转换为无向图,directed = FALSE确保a关联b和b关联a被视为同一条边components(graph):计算图的连通分量,返回每个节点所属的组编号- 最后通过
arrange()按分组和数值排序,得到和期望一致的输出
这种方法的优势在于:
- 效率高:igraph的连通分量算法时间复杂度接近线性,处理大型数据集远快于多次自连接
- 逻辑清晰:直接用图论模型映射问题,不需要手动处理递归关联的层级迭代
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

