You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NetworkX添加同名节点时如何指定对象属性为节点显示标签

核心原因

NetworkX判定节点是否重复的依据是传入的节点唯一标识值:

  • 原代码用node.caption作为节点ID传入,相同字符串会被判定为同一个节点,因此两个caption为"A"、两个caption为"B"的节点会被自动合并,和预期结构不符
  • 直接传入Node实例作为节点时,Python默认按对象内存地址做哈希判定,不同实例就算属性值完全一致也会被识别为独立节点,图结构符合预期,但默认标签直接取节点ID的字符串表示,也就是对象的内存地址输出,不会自动读取caption属性显示。
实现方法

不需要修改自定义Node类,直接以Node实例作为节点存入MultiGraph即可,NetworkX原生支持传入任意可哈希对象作为节点。要实现自定义标签显示,只需要单独构建标签映射字典,在绘图时指定标签参数即可,不需要额外修改库配置。
具体修改点:

  • 节点、边添加逻辑不再传入caption值,直接传入Node实例本身
  • 构建标签映射字典,key为节点对象,value为节点需要显示的caption属性值
  • 绘图时调用标签绘制接口传入自定义标签字典,替换默认的标签生成逻辑
  • 修正原边绘制代码中多余的文字标注参数,避免边上显示无关内容
修改后可直接运行的代码
import networkx as nx
import matplotlib.pyplot as plt

# 自定义Node类保持原有定义不变
class Node:
    def __init__(self, caption, id, parent_id, parent_connections, children):
        self.caption = caption                          
        self.id = id                                    
        self.parent_id = parent_id                      
        self.parent_connections = parent_connections    
        self.children = children                        


G = nx.MultiGraph()
# 初始化所有示例节点
node_x = Node(caption="X", id=1, parent_id=None, parent_connections=[], children=[])
node_y = Node(caption="Y", id=2, parent_id=1, parent_connections=["first connection"], children=[])
node_z = Node(caption="Z", id=3, parent_id=1, parent_connections=["first connection"], children=[])
node_a_y = Node(caption="A", id=4, parent_id=2, parent_connections=["first connection", "second connection", "third connection"], children=[])
node_b_y = Node(caption="B", id=5, parent_id=2, parent_connections=["first connection"], children=[])
node_a_z = Node(caption="A", id=6, parent_id=3, parent_connections=["first connection"], children=[])
node_b_z = Node(caption="B", id=7, parent_id=3, parent_connections=["first connection"], children=[])

all_nodes = [node_x, node_y, node_z, node_a_y, node_b_y, node_a_z, node_b_z]
# 填充每个节点的children列表
for node in all_nodes:
    for other_node in all_nodes:
        if other_node is not node and other_node.parent_id == node.id:
            node.children.append(other_node)

# 构建自定义标签映射
node_labels = {node: node.caption for node in all_nodes}

# 直接添加节点实例、边实例,不再用caption作为节点唯一标识
for node in all_nodes:
    G.add_node(node)
    for child in node.children:
        for conn_idx in range(len(child.parent_connections)):
            G.add_edge(node, child, length=10)

# 执行绘图
pos = nx.spring_layout(G)
nx.draw_networkx_nodes(G, pos, node_color="r", node_size=100, alpha=1)
# 传入自定义标签绘制节点文字
nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=10)

ax = plt.gca()
for e in G.edges:
    ax.annotate("",
                xy=pos[e[0]], xycoords="data",
                xytext=pos[e[1]], textcoords="data",
                arrowprops=dict(arrowstyle="-", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle="arc3,rad=rrr".replace("rrr",str(0.3*e[2])),
                                ),
                )
plt.axis('off')
plt.show()
补充说明

该标签自定义逻辑是通用的:不管你后续用什么作为节点唯一标识(数字ID、自定义哈希值、对象实例),只要给绘图接口的labels参数传入{节点ID: 显示文本}格式的字典,就能自由控制节点显示内容,不需要依赖节点ID本身的字符串值。如果后续需要给节点、边添加其他显示属性(比如边的连接说明、节点颜色映射),也可以用同样的字典映射方式实现。


内容的提问来源于stack exchange,提问作者humanic_dolphin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.02 04:45:38