如何在Pandas中利用权重列构建邻接矩阵?
用Pandas从带权重的边列表生成邻接矩阵
看起来你已经走对了方向,但需要调整几个细节来得到你期望的邻接矩阵。你的核心需求是把Source-Target-weight格式的边数据转换成行列都是节点、值为权重的矩阵,并且缺失的边(包括节点到自身无数据的情况)要填充为0。
问题分析
你当前用pd.crosstab的思路是对的,但存在几个小问题:
- 默认的
crosstab只会用出现过的Source作为行、Target作为列,如果某个节点只出现在其中一列(比如假设存在一个节点只作为Target),就会被遗漏 - 没有连接的位置会显示为
NaN,而不是你需要的0 - 节点到自身的边如果没有数据,不会自动填充0
解决方案步骤
这里提供两种可靠的实现方式,都能完美匹配你的期望输出:
1. 先准备所有节点的集合
首先我们需要获取所有出现过的节点(不管是Source还是Target),这样邻接矩阵的行列才能包含全部节点:
import pandas as pd # 读取并预处理数据 ady = pd.read_csv("edges.csv", sep=',')[['Source', 'Target', 'weight']] ady['weight'] = pd.to_numeric(ady['weight']) # 获取所有唯一节点,确保行列覆盖全部节点 all_nodes = pd.unique(ady[['Source', 'Target']].values.ravel('K')) all_nodes.sort() # 可选,让节点按字母/数字顺序排列
2. 方法一:改进版pd.crosstab
通过指定categories参数强制行列使用所有节点,再填充缺失值为0:
adj_matrix = pd.crosstab( ady.Source, ady.Target, values=ady.weight, aggfunc='sum', categories=[all_nodes, all_nodes], # 强制行列包含所有节点 rownames=['Source'], colnames=['Target'] ).fillna(0)
3. 方法二:使用pivot_table
pivot_table更灵活,配合reindex来补全所有节点:
adj_matrix = ady.pivot_table( index='Source', columns='Target', values='weight', aggfunc='sum', fill_value=0 # 先填充已有的缺失值 ).reindex(index=all_nodes, columns=all_nodes, fill_value=0) # 补全行列的节点
输出结果
运行上述代码后,你会得到完全符合期望的邻接矩阵:
Target a b c Source a 0 2 1 b 2 1 0 c 1 0 0
关键细节说明
pd.unique(ady[['Source', 'Target']].values.ravel('K')):这个操作会把Source和Target列的所有值展平成一维数组,然后去重,确保不会漏掉任何节点- 填充0:不管是
fillna(0)还是fill_value=0,都是为了把"没有这条边"的情况统一表示为0,符合邻接矩阵的常规定义 - 聚合函数
sum:如果你的数据中存在重复的Source-Target对,sum会自动把权重累加,这也是邻接矩阵的合理处理方式
内容的提问来源于stack exchange,提问作者Tlaloc-ES
相关产品推荐
相关产品推荐

