NetworkX中因节点/边属性赋值错误引发KeyError的问题排查与解决
解决NetworkX中节点属性的KeyError问题
咱们先拆解一下你遇到的问题根源,再一步步修复代码:
为什么会出现KeyError?
你当前的代码用nx.from_pandas_edgelist(filtered, 'Source', 'Target', edge_attr=True)导入数据时,把所有除了Source和Target之外的列(也就是Label_Source和Label_Target)都当成了边属性,而不是节点属性。所以这些标签数据现在存在于G.edges[v,w]里,而不是G.nodes[v]里——你去节点属性里找Label_Source,自然会触发KeyError。
这就是你参考的项目里没有遇到这个问题的原因:人家的数据集里节点属性是单独维护的,而你的数据把节点属性混在了边表中。
修复步骤:先分离节点属性和边数据
我们需要先把所有节点的标签整理出来,再分别导入边和节点属性:
1. 整理节点属性数据
首先从你的边表中提取所有唯一节点及其对应的标签(注意:同一个节点可能既出现在Source列又出现在Target列,要确保每个节点只保留一个标签):
import pandas as pd import networkx as nx from matplotlib import pyplot as plt # 假设你的原始数据存在filtered这个DataFrame里 # 提取源节点-标签对 source_nodes = filtered[['Source', 'Label_Source']].rename(columns={'Source': 'Node', 'Label_Source': 'Label'}) # 提取目标节点-标签对 target_nodes = filtered[['Target', 'Label_Target']].rename(columns={'Target': 'Node', 'Label_Target': 'Label'}) # 合并并去重(如果同一节点多次出现,保留第一个出现的标签) node_attrs = pd.concat([source_nodes, target_nodes]).drop_duplicates(subset='Node', keep='first')
2. 创建图并导入正确的属性
先导入边数据(不要把Label列当成边属性),再给节点添加标签属性:
# 只导入边,不导入额外的边属性 G = nx.from_pandas_edgelist(filtered, 'Source', 'Target') # 把节点标签转换成字典格式:{节点名: 标签值} label_dict = node_attrs.set_index('Node')['Label'].to_dict() # 给图中的节点添加Label属性 nx.set_node_attributes(G, label_dict, 'Label')
3. 修正节点颜色和边属性的代码
现在所有节点都有了Label属性,我们可以正确使用它来设置颜色和判断边的类型:
# 设置节点颜色:Label为0.0时用蓝色,否则用绿色 node_color = ['#1f78b4' if G.nodes[v]['Label'] == 0.0 else '#33a02c' for v in G.nodes] # 遍历边,设置internal属性(同标签节点之间的边为内部边) for v, w in G.edges: if G.nodes[v]['Label'] == G.nodes[w]['Label']: G.edges[v, w]['internal'] = True else: G.edges[v, w]['internal'] = False
4. 可视化验证
最后可以正常绘制图了:
df_pos = nx.spring_layout(G, k=0.3) nx.draw_networkx(G, df_pos, node_color=node_color) plt.show()
额外说明
你提到的“遍历字符串而非索引”不是问题:NetworkX的节点可以是任意可哈希的类型(字符串、数字都可以),遍历G.nodes就是遍历这些节点的标识,完全没问题。核心问题还是一开始把节点属性错误地当成了边属性导入。
内容的提问来源于stack exchange,提问作者LdM
相关产品推荐
相关产品推荐

