NetworkX节点多属性分配报KeyError及多属性网络构建实现
报错核心原因
你遇到的KeyError: 87.5完全来自之前的节点收集逻辑错误:
- 写的
collist = df.drop('Weight', axis=1).melt('Label').dropna()执行后,melt生成的value列会把Attribute列的数值(比如第一行的87.5)也当成待计算度数的节点。这些数值从来没有作为Source/Target出现在边表里,图中不存在对应节点,查询度数时自然触发报错。 - 之前绑定节点属性的逻辑没有对齐映射关系:没有区分“Source节点带Attribute、Label属性,Target节点不带任何专属属性”的规则,直接硬套属性映射,后续计算时很容易出现属性错位。
完整可运行的修正实现
1. 图构建与属性绑定
因为Attribute、Label是仅属于Source列节点的属性,不需要对所有节点通用,先提取唯一的属性映射表,避免重复边干扰属性对齐:
import pandas as pd import networkx as nx import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap # 读取你的边表数据(替换成你自己的df加载逻辑即可) df = pd.DataFrame({ 'Attribute': [87.5, 12.5, 12.5, 43.5], 'Source': ['Heisenberg', 'Beckham', 'Beckham', 'water'], 'Target': ['Pauli', 'Messi', 'Maradona', 'melon'], 'Weight': [66.3, 38.1, 12, 33.6], 'Label': [1, 0, 0, 1] }) # 提取Source节点的专属属性,按Source去重(同一个Source出现在多行时取一次属性值即可) source_attr_map = df[['Source', 'Attribute', 'Label']].drop_duplicates(subset=['Source']) attr_dict = source_attr_map.set_index('Source')['Attribute'].to_dict() label_dict = source_attr_map.set_index('Source')['Label'].to_dict() # 建图,边属性绑定Weight G = nx.from_pandas_edgelist(df, source='Source', target='Target', edge_attr='Weight') # 给匹配到的Source节点绑定Attribute、Label属性,无匹配的Target节点自动跳过 nx.set_node_attributes(G, attr_dict, 'Attribute') nx.set_node_attributes(G, label_dict, 'Label')
2. 节点大小、属性值计算
这里严格只从Source、Target两列收集所有真实存在的节点,彻底避免之前把Attribute数值当成节点的错误:
# 收集图里所有真实节点(仅来自Source和Target列) all_nodes = pd.concat([df['Source'], df['Target']]).unique() # 按节点列表计算对应大小(与度数成正比) node_sizes = [100 * G.degree[node] for node in all_nodes] # 生成每个节点对应的颜色值:Source节点用自身Label值,Target节点用默认中性值 node_colors = [G.nodes[node].get('Label', 0.5) for node in all_nodes]
3. 按参考逻辑更新Attribute值
完全匹配邻域平均的参考实现逻辑,同时跳过没有Attribute初始值的Target节点,不会出现属性计算错位:
updated_attrs = {} for node in G.nodes: # 没有初始Attribute的节点(即Target节点),保持原状态 if 'Attribute' not in G.nodes[node]: updated_attrs[node] = None continue # 收集所有带Attribute属性的邻居值,过滤不带属性的Target节点 neighbor_attrs = [ G.nodes[neighbor]['Attribute'] for neighbor in G.neighbors(node) if 'Attribute' in G.nodes[neighbor] ] # 计算邻域平均 if neighbor_attrs: new_val = (sum(neighbor_attrs) + G.nodes[node]['Attribute']) / (len(neighbor_attrs) + 1) else: new_val = G.nodes[node]['Attribute'] updated_attrs[node] = new_val # 统一把更新后的值写回节点 for node, new_val in updated_attrs.items(): if new_val is not None: G.nodes[node]['Attribute'] = new_val
4. 绘图匹配规则
- 边粗细与Weight值正相关
- 节点颜色按规则映射:Label=1对应黄色,Label=0对应蓝色
# 固定布局种子,保证每次出图位置一致 pos = nx.spring_layout(G, seed=42) # 缩放边权重,避免边过粗 edge_widths = [G.edges[edge]['Weight'] / 20 for edge in G.edges] # 定义颜色映射:0=蓝色,1=黄色 color_map = ListedColormap(['#1a75bb', '#ffdd22']) nx.draw_networkx_labels(G, pos, font_size=10) nx.draw_networkx_nodes( G, pos, nodelist=all_nodes, node_size=node_sizes, node_color=node_colors, cmap=color_map, vmin=0, vmax=1 ) nx.draw_networkx_edges(G, pos, width=edge_widths) plt.axis('off') plt.show()
效果校验
运行后不会再出现KeyError报错:
- 所有节点的大小与自身度数成正比
- Source节点的颜色完全匹配Label规则(1黄0蓝),Target节点为默认中间色
- Attribute属性仅绑定在Source节点上,更新逻辑与参考实现完全一致
- 边的粗细与Weight值直接对应
内容的提问来源于stack exchange,提问作者V_sqrt
相关产品推荐
相关产品推荐

