使用NetworkX高效构建企业交易网络的最优方法咨询
高效使用NetworkX从企业交易DataFrame构建网络
我有一个存储企业间交易信息的DataFrame,数据如下:
import pandas as pd df = pd.DataFrame({ 'idA': [4, 3, 3, 1], 'idB': [5, 7, 6, 4], 'amount': [300, 150, 289, 189], 'nameA': ['xxx', 'kkk', 'kkk', 'hhh'], 'nameB': ['yyy', 'uuu', 'vvv', 'iii'] })
我目前用下面的代码构建NetworkX图:
import networkx as nx G=nx.Graph() for i in df.index: G.add_node(df['idA'][i], name = df['nameA'][i]) G.add_node(df['idB'][i], name = df['nameB'][i]) G.add_edge(df['idA'][i], df['idB'][i], weight = df['amount'][i] )
请问有没有更高效的实现方式?
当然有更高效的实现方式!你的循环写法在小数据量下完全没问题,但当DataFrame行数上去之后,逐行遍历的开销会越来越明显。NetworkX专门提供了适配Pandas的工具函数,能帮你简化代码同时大幅提升效率:
方法1:用from_pandas_edgelist快速建边,再批量加节点属性
from_pandas_edgelist可以直接从DataFrame生成图的边集,还能自动创建关联节点,省去手动循环加边的步骤。之后我们把节点ID和名称的映射整理成字典,批量更新节点属性即可:
import networkx as nx import pandas as pd # 第一步:从DataFrame直接生成边与节点 G = nx.from_pandas_edgelist( df, source='idA', target='idB', edge_attr='amount', # 自动把amount设为边的weight属性 create_using=nx.Graph() ) # 第二步:整理所有节点的name映射 node_names = {} for _, row in df.iterrows(): node_names[row['idA']] = row['nameA'] node_names[row['idB']] = row['nameB'] # 批量设置节点属性,比逐次add_node高效得多 nx.set_node_attributes(G, node_names, 'name')
方法2:彻底去掉循环的节点属性整理
如果想连节点映射的循环都省掉,可以用Pandas的concat把idA/nameA、idB/nameB合并成统一的Series,再转成字典:
# 合并节点ID与对应名称的映射,去重后转成字典 node_series = pd.concat([ df[['idA', 'nameA']].rename(columns={'idA': 'id', 'nameA': 'name'}), df[['idB', 'nameB']].rename(columns={'idB': 'id', 'nameB': 'name'}) ]).drop_duplicates(subset='id').set_index('id')['name'] node_names = node_series.to_dict() # 同样用from_pandas_edgelist建图,再批量设置属性 G = nx.from_pandas_edgelist(df, 'idA', 'idB', edge_attr='amount', create_using=nx.Graph()) nx.set_node_attributes(G, node_names, 'name')
为什么这些方法更高效?
from_pandas_edgelist是NetworkX内部优化过的函数,用矢量化操作替代了Python层面的循环,大数据量下速度提升非常明显。- 批量设置节点属性的方式,减少了大量重复的
add_node函数调用开销,比逐行添加节点高效得多。
如果你的DataFrame有几十万甚至上百万行,这种优化带来的速度差异会特别显著。
内容的提问来源于stack exchange,提问作者emax
相关产品推荐
相关产品推荐

