Python中基于DataFrame两列构建网络并添加聚类ID列的方法
刚好我之前处理过类似的需求,给你分享两个高效的实现方案,分别用igraph和networkx结合pandas,解决你之前遇到的速度慢的问题:
方案一:用igraph实现(高效首选)
igraph的底层是用C实现的,处理大规模图数据的速度比纯Python实现的库快很多,完全能对标你R语言里的igraph包效率。具体步骤如下:
- 导入所需库
- 从DataFrame的边列直接构建无向图
- 获取连通分量(也就是你说的聚类)
- 建立节点到聚类ID的映射,用向量化操作快速赋值回原DataFrame
完整代码示例:
import pandas as pd import igraph as ig # 模拟你的原始DataFrame df = pd.DataFrame({ "col1": ["A", "B", "C", "D", "E", "F"], "col2": ["B", "C", "A", "E", "D", "G"] }) # 从边数据构建无向图,自动识别所有节点 g = ig.Graph.DataFrame(df[["col1", "col2"]], directed=False) # 获取连通分量聚类结果 clusters = g.clusters() # 创建节点到聚类ID的映射Series,索引是节点名,值是聚类ID cluster_map = pd.Series(clusters.membership, index=g.vs["name"]) # 快速将聚类ID映射回原DataFrame的col1列对应的行 df["cluId"] = df["col1"].map(cluster_map)
为什么这个方案快?
- igraph的图构建和聚类计算都是底层C实现,处理百万级边也毫无压力
- 用
pd.Series.map()做向量化映射,比循环遍历每一行快几个数量级
方案二:用networkx实现(灵活兼容)
如果你更倾向于用networkx,也可以用高效的方式实现,避免之前的慢速度问题。核心是一次性构建节点到聚类ID的字典映射,而不是逐个节点查找:
完整代码示例:
import pandas as pd import networkx as nx # 同样的模拟DataFrame df = pd.DataFrame({ "col1": ["A", "B", "C", "D", "E", "F"], "col2": ["B", "C", "A", "E", "D", "G"] }) # 从DataFrame边列构建无向图 g = nx.from_pandas_edgelist(df, source="col1", target="col2", create_using=nx.Graph()) # 获取所有连通分量,用字典推导式快速生成节点-聚类ID映射 cluster_map = {} for cluster_id, component in enumerate(nx.connected_components(g)): for node in component: cluster_map[node] = cluster_id # 映射回原DataFrame df["cluId"] = df["col1"].map(cluster_map)
优化点说明:
- 用
nx.connected_components()批量获取所有连通分量,避免重复遍历图 - 字典推导式一次性完成所有节点的ID赋值,比循环每行去查询聚类快很多
注意事项
不管用哪种方案,都要确保col1和col2的节点类型一致(比如都是字符串或都是整数),如果类型不统一,可以先转成字符串:
df["col1"] = df["col1"].astype(str) df["col2"] = df["col2"].astype(str)
内容的提问来源于stack exchange,提问作者hm6
相关产品推荐
相关产品推荐

