NetworkX节点标签与颜色未按预期显示,求问题排查
问题
我正在编写NetworkX与Neo4j交互的工具包,练习自定义节点/边属性,想模拟Neo4j的显示规则——根据节点的['data']['label']设置节点标签、['data']['color']设置节点颜色,根据边的['label']设置边标签。但运行代码后只有边标签符合预期,节点标签和颜色都不对。打印的标签、颜色字典看起来符合NetworkX文档要求,但绘图结果就是不对,请问哪里出错了?
代码如下:
import networkx as nx import matplotlib.pyplot as plt def draw_labeled_net(G: nx.DiGraph): plt.figure(figsize = (12,12)) pos = nx.spring_layout(G) nx.draw_networkx_nodes(G, pos, node_color = get_node_colors(G)) nx.draw_networkx_labels(G, pos, labels = get_node_labels(G), font_size = 12) nx.draw_networkx_edges(G, pos, edge_color = 'tab:red') nx.draw_networkx_edge_labels(G, pos, edge_labels = get_edge_labels(G)) plt.show() def get_node_labels(G: nx.DiGraph): labels = {} for i in range(len(G.nodes)): try: labels[i] = G.nodes[i]['data']['label'] except KeyError as e: labels[i] = 'None' print() print('Node labels:') print(labels) def get_edge_labels(G: nx.DiGraph): edge_labels = {} for edge in list(G.edges): try: edge_labels[edge] = G.get_edge_data(*edge)['label'] except KeyError as e: edge_labels[edge] = 'None' def get_node_colors(G: nx.DiGraph): colors = {} for i in range(len(G.nodes)): try: colors[i] = f"tab:{G.nodes[i]['data']['color']}" except KeyError as e: colors[i] = 'tab:red' print() print('Node colors:') print(colors) G = nx.DiGraph() G.add_node(0, data = {'color': 'green', 'label': 'Person'}) G.nodes[0] G.add_edge(0, 1, label = 'hitBy') draw_labeled_net(G)
绘图结果:节点显示默认的数字ID(0、1),颜色为默认蓝色,仅边标签hitBy正常显示。
问题分析与解决
核心错误:函数缺少返回值
get_node_labels和get_node_colors函数仅打印了生成的字典,但没有用return语句返回结果。调用这两个函数时,实际传给NetworkX绘图函数的是None,所以绘图时会自动使用默认的节点标签(节点ID)和默认颜色。
次要问题:节点遍历方式不严谨
用range(len(G.nodes))遍历节点,仅在节点ID是连续整数时有效。如果节点ID是非连续整数或字符串,这种遍历方式会直接出错,正确的做法是直接遍历G.nodes获取所有节点ID。
修正后的代码
import networkx as nx import matplotlib.pyplot as plt def draw_labeled_net(G: nx.DiGraph): plt.figure(figsize=(12, 12)) pos = nx.spring_layout(G) # 获取颜色字典并转为节点顺序对应的列表(避免字典键顺序问题) node_color_dict = get_node_colors(G) node_color_list = [node_color_dict[node] for node in G.nodes] nx.draw_networkx_nodes(G, pos, node_color=node_color_list) # 传入返回的标签字典 nx.draw_networkx_labels(G, pos, labels=get_node_labels(G), font_size=12) nx.draw_networkx_edges(G, pos, edge_color='tab:red') nx.draw_networkx_edge_labels(G, pos, edge_labels=get_edge_labels(G)) plt.show() def get_node_labels(G: nx.DiGraph): labels = {} # 直接遍历所有节点ID for node in G.nodes: try: labels[node] = G.nodes[node]['data']['label'] except KeyError: labels[node] = 'None' print('\nNode labels:') print(labels) # 添加返回语句 return labels def get_edge_labels(G: nx.DiGraph): edge_labels = {} for edge in G.edges: try: edge_labels[edge] = G.get_edge_data(*edge)['label'] except KeyError: edge_labels[edge] = 'None' # 补充返回语句 return edge_labels def get_node_colors(G: nx.DiGraph): colors = {} # 直接遍历所有节点ID for node in G.nodes: try: colors[node] = f"tab:{G.nodes[node]['data']['color']}" except KeyError: colors[node] = 'tab:red' print('\nNode colors:') print(colors) # 添加返回语句 return colors G = nx.DiGraph() G.add_node(0, data={'color': 'green', 'label': 'Person'}) G.add_edge(0, 1, label='hitBy') draw_labeled_net(G)
额外说明
nx.draw_networkx_nodes的node_color参数支持字典,但转为与G.nodes顺序一致的列表更稳妥,可避免字典键顺序不匹配导致的颜色错位问题。
内容的提问来源于stack exchange,提问作者Daniel Frees
相关产品推荐
相关产品推荐

