使用NetworkX绘制数据时遭遇节点映射KeyError问题求助
问题描述
我首次尝试使用NetworkX,以下是我的示例代码:
import pandas as pd import numpy as np data = [{'Circuit_Number': 1,'Description':'Stadium', 'Duration':10, 'Device_County':'Westchester', 'Picklist':1000, 'Postlist':50000}, {'Circuit_Number': 2, 'Description':'Stadium', 'Duration':12, 'Device_County':'Westchester', 'Picklist':3000, 'Postlist':40000}, {'Circuit_Number': 2, 'Description':'Arena', 'Duration':11, 'Device_County':'Westchester', 'Picklist':7000, 'Postlist':50000}, {'Circuit_Number': 3, 'Description':'Arena', 'Duration':8, 'Device_County':'Westchester', 'Picklist':3000, 'Postlist':40000}, {'Circuit_Number': 3, 'Description':'Casino', 'Duration':6, 'Device_County':'Queens', 'Picklist':5000, 'Postlist':6000}, {'Circuit_Number': 4, 'Description':'Casino', 'Duration':20, 'Device_County':'Queens', 'Picklist':5000, 'Postlist':4000}, {'Circuit_Number': 4, 'Description':'Library', 'Duration':15, 'Device_County':'Brooklyn', 'Picklist':5000, 'Postlist':9000}, {'Circuit_Number': 5, 'Description':'Library', 'Duration':7, 'Device_County':'Brooklyn', 'Picklist':6000, 'Postlist':10000}] df = pd.DataFrame(data) df ###################################################################################### import networkx as nx import matplotlib.pyplot as plt # Input data files check from subprocess import check_output import warnings warnings.filterwarnings('ignore') G = nx.Graph() for index, row in df.iterrows(): G.add_node(row['Circuit_Number'], group=row['Description'], nodesize=row['Duration']) for index, row in df.iterrows(): G.add_weighted_edges_from([(row['Device_County'], row['Picklist'], row['Postlist'])]) def draw_graph(G,size): nodes = G.nodes() color_map = {1000:'#f09494', 3000:'#eebcbc', 5000:'#72bbd0', 6000:'#91f0a1', 7000:'#629fff'} node_color = [color_map[d['Duration']] for n,d in G.nodes(data=True)] node_size = [d['Duration']*10 for n,d in G.nodes(data=True)] pos = nx.drawing.spring_layout(G,k=0.70,iterations=60) plt.figure(figsize=size) nx.draw_networkx(G,pos=pos,node_color=node_color,node_size=node_size,edge_color='#FFDEA2') plt.show() draw_graph(G,size=(30,30))
运行后出现如下错误:
node_color = [color_map[d['Duration']] for n,d in G.nodes(data=True)] KeyError: 'Duration'
我尝试将DataFrame中的数据导入NetworkX,生成类似下图的网络图,但无法成功绘制,请求帮助解决该问题。
问题分析与解决
核心问题
- 节点属性缺失:你只给
Circuit_Number类型的节点添加了nodesize(对应Duration)属性,但添加边时自动创建的Device_County、Picklist节点没有Duration属性,遍历所有节点时触发KeyError。 - 颜色映射逻辑错误:
color_map的键是Picklist的数值(1000/3000等),但你用Duration(6/7/10等)去匹配,两者完全不对应。 - 节点关系混乱:原代码没有明确节点类型,导致Circuit、地区、Picklist等不同类型节点混在一起,不符合参考图的多类型节点网络结构。
修正后的代码
import pandas as pd import networkx as nx import matplotlib.pyplot as plt # 原始数据 data = [{'Circuit_Number': 1,'Description':'Stadium', 'Duration':10, 'Device_County':'Westchester', 'Picklist':1000, 'Postlist':50000}, {'Circuit_Number': 2, 'Description':'Stadium', 'Duration':12, 'Device_County':'Westchester', 'Picklist':3000, 'Postlist':40000}, {'Circuit_Number': 2, 'Description':'Arena', 'Duration':11, 'Device_County':'Westchester', 'Picklist':7000, 'Postlist':50000}, {'Circuit_Number': 3, 'Description':'Arena', 'Duration':8, 'Device_County':'Westchester', 'Picklist':3000, 'Postlist':40000}, {'Circuit_Number': 3, 'Description':'Casino', 'Duration':6, 'Device_County':'Queens', 'Picklist':5000, 'Postlist':6000}, {'Circuit_Number': 4, 'Description':'Casino', 'Duration':20, 'Device_County':'Queens', 'Picklist':5000, 'Postlist':4000}, {'Circuit_Number': 4, 'Description':'Library', 'Duration':15, 'Device_County':'Brooklyn', 'Picklist':5000, 'Postlist':9000}, {'Circuit_Number': 5, 'Description':'Library', 'Duration':7, 'Device_County':'Brooklyn', 'Picklist':6000, 'Postlist':10000}] df = pd.DataFrame(data) G = nx.Graph() # 1. 添加Circuit节点,明确标注类型和属性 for _, row in df.iterrows(): circuit_node = f"Circuit_{row['Circuit_Number']}" G.add_node(circuit_node, node_type="circuit", duration=row['Duration'], group=row['Description']) # 2. 添加关联节点(设施、地区、Picklist)并建立连接 for _, row in df.iterrows(): circuit_node = f"Circuit_{row['Circuit_Number']}" # 连接Circuit与设施(Description) desc_node = row['Description'] G.add_node(desc_node, node_type="facility") G.add_edge(circuit_node, desc_node, weight=row['Postlist']) # 连接Circuit与地区(Device_County) county_node = row['Device_County'] G.add_node(county_node, node_type="county") G.add_edge(circuit_node, county_node, weight=row['Postlist']) # 连接Circuit与Picklist picklist_node = row['Picklist'] G.add_node(picklist_node, node_type="picklist") G.add_edge(circuit_node, picklist_node, weight=row['Postlist']) def draw_graph(G, size): # 按节点类型分配颜色 color_map = { "circuit": "#f09494", "facility": "#eebcbc", "county": "#72bbd0", "picklist": "#91f0a1" } node_color = [] node_size = [] for n, d in G.nodes(data=True): # Circuit节点大小由Duration决定,其他节点统一大小 if d['node_type'] == "circuit": node_size.append(d['duration'] * 100) else: node_size.append(600) node_color.append(color_map[d['node_type']]) pos = nx.spring_layout(G, k=0.70, iterations=60) plt.figure(figsize=size) # 绘制节点、边和标签 nx.draw_networkx_nodes(G, pos, node_color=node_color, node_size=node_size) nx.draw_networkx_edges(G, pos, edge_color='#FFDEA2', width=[d['weight']/10000 for _,_,d in G.edges(data=True)]) nx.draw_networkx_labels(G, pos, font_size=10) plt.show() draw_graph(G, size=(30,30))
关键修正说明
- 节点类型明确:给所有节点添加
node_type属性,避免属性缺失报错,同时区分不同类型节点。 - 逻辑关系清晰:建立Circuit节点与设施、地区、Picklist的连接,符合参考图的多节点类型网络结构。
- 可视化优化:按节点类型分配颜色,Circuit节点大小关联Duration,边宽度关联Postlist,更贴合数据含义。
- 避免重复节点:NetworkX自动忽略重复添加的节点,无需手动去重。
内容的提问来源于stack exchange,提问作者ASH
相关产品推荐
相关产品推荐

