基于NetworkX绘制带权边图的技术问题(含Pandas权重矩阵)
嘿,我懂你现在的困扰——你想基于姓名节点的权重矩阵,让NetworkX画出的边粗细对应权重大小,但之前的代码没达到预期对吧?问题主要出在权重矩阵的格式转换和边属性的正确传递上,咱们一步步来修正:
问题根源
你之前的代码用了nx.from_pandas_edgelist(),但输入的bin_nom是宽格式的权重矩阵(姓名作为行/列),而这个函数需要的是长格式的边列表(每条边一行,包含源节点、目标节点、权重)。另外,edge_attr参数的用法也不对,你之前传了列名列表,应该指定权重列的名称。
修正步骤
1. 把权重矩阵转成边列表
首先需要将宽格式的权重矩阵转换为NetworkX能识别的长格式边列表,同时过滤掉无效边(比如权重为0、自环):
# 假设你的权重矩阵名为 name_weight_matrix,行和列都是姓名 edge_df = name_weight_matrix.stack().reset_index() # 重命名列,明确源节点、目标节点、权重 edge_df.columns = ["source", "target", "weight"] # 过滤掉自环和权重为0的边(按需调整) edge_df = edge_df[(edge_df["source"] != edge_df["target"]) & (edge_df["weight"] > 0)]
2. 正确构建带权重的图
现在用转换后的边列表构建图,确保权重被正确作为边属性存入:
G = nx.from_pandas_edgelist( edge_df, source="source", target="target", edge_attr="weight", # 明确指定权重列,让边携带权重信息 create_using=nx.Graph() )
3. 按权重绘制边
绘制时,从图的边属性中提取权重,缩放后作为边的宽度参数,这样就能实现“权重越大边越粗”的效果:
import matplotlib.pyplot as plt import networkx as nx plt.figure(figsize=(35, 35)) # 提取所有边的权重,并缩放(这里乘以5是为了让粗细差异更明显,可按需调整) edge_weights = [G[u][v]["weight"] for u, v in G.edges()] scaled_widths = [w * 5 for w in edge_weights] # 调整绘图选项,把width设为缩放后的权重 options = { 'edge_color': '#eebcbc', 'width': scaled_widths, 'with_labels': True, 'font_weight': 'regular', } # 节点大小逻辑和你之前保持一致 node_degrees = dict(G.degree) layout_pos = nx.spring_layout(G, k=0.85, iterations=100) nx.draw( G, pos=layout_pos, node_color='blue', nodelist=node_degrees.keys(), node_size=[v * 100 for v in node_degrees.values()], **options ) # 设置节点边框颜色 ax = plt.gca() ax.collections[0].set_edgecolor("#000007") plt.show()
额外小技巧
- 如果权重值范围过大(比如从1到100),可以用标准化处理避免边太粗或太细:
from sklearn.preprocessing import MinMaxScaler scaler = MinMaxScaler(feature_range=(1, 10)) # 把权重缩放到1-10的范围作为边宽 scaled_widths = scaler.fit_transform([[w] for w in edge_weights]).flatten() - 如果想给边添加权重标签,可以用
nx.draw_networkx_edge_labels():nx.draw_networkx_edge_labels(G, pos=layout_pos, edge_labels={(u, v): G[u][v]["weight"] for u, v in G.edges()})
内容的提问来源于stack exchange,提问作者user9176398
相关产品推荐
相关产品推荐

