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

Matplotlib与Networkx绘制自环节点图及邻接矩阵绘图优化咨询

我来帮你解决这个问题!你遇到的自环显示成点、节点名称无法添加的问题,主要是因为手动自定义绘图时没处理自环的渲染逻辑,而且其实NetworkX本身就有一套完整的工具,能轻松搞定基于邻接矩阵的图绘制,包括自环和节点标签,根本不用自己造轮子~

更优实现方案:用NetworkX原生工具搞定

1. 从邻接矩阵快速构建图

NetworkX提供了直接从numpy数组(邻接矩阵)创建图的方法,不管是有向图还是无向图,自环都会被自动识别:

import numpy as np
import networkx as nx
import matplotlib.pyplot as plt

# 示例邻接矩阵,(1,1)位置的1代表节点1有自环
adj_matrix = np.array([
    [0, 1, 0],
    [0, 1, 1],
    [1, 0, 0]
])

# 创建有向图(如果是无向图,替换为nx.Graph)
G = nx.DiGraph(adj_matrix)

如果你的邻接矩阵有权重,NetworkX会自动给边添加weight属性,后续可以直接调用。

2. 正确绘制带自环+节点标签的图

NetworkX的原生绘图函数已经内置了自环处理逻辑,你只需要通过参数控制自环的显示样式,同时添加节点标签即可:

plt.figure(figsize=(8, 6))

# 获取节点布局(用spring_layout保证位置固定,方便复现)
pos = nx.spring_layout(G, seed=42)

# 绘制节点
nx.draw_networkx_nodes(G, pos, node_size=700, node_color='lightblue', alpha=0.8)

# 绘制边(包括自环!关键参数是connectionstyle控制自环弧度)
nx.draw_networkx_edges(
    G, pos,
    edgelist=G.edges(),
    arrowstyle='->',  # 箭头样式
    arrowsize=15,     # 箭头大小
    connectionstyle='arc3,rad=0.2',  # rad越大,自环向外凸的弧度越大,避免和节点重叠
    edge_color='gray',
    linewidth=1.5
)

# 绘制节点名称(解决你说的无法添加节点名称问题)
nx.draw_networkx_labels(G, pos, font_size=12, font_weight='bold')

# (可选)绘制边的权重
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=10)

plt.axis('off')
plt.show()

这里的connectionstyle参数是解决自环显示成点的核心:通过设置rad值,让自环以圆弧形式呈现,不会和节点重叠成一个点。

3. 如果必须自定义绘图(比如你的原有函数)

如果你因为特殊需求必须自己实现绘图逻辑,那需要单独处理自环的渲染,同时添加节点标签:

from matplotlib.patches import FancyArrowPatch, Circle

def draw_network(G, pos, ax):
    # 绘制节点+节点名称
    for n in G.nodes():
        # 绘制节点圆圈
        node_circle = Circle(pos[n], radius=0.05, alpha=0.7, color='lightblue')
        ax.add_patch(node_circle)
        # 添加节点名称
        ax.text(
            pos[n][0], pos[n][1], str(n),
            fontsize=12, ha='center', va='center', fontweight='bold'
        )
    
    # 绘制边:区分普通边和自环
    for u, v in G.edges():
        if u == v:
            # 自环:用圆弧绘制
            self_loop_rad = 0.2
            arrow = FancyArrowPatch(
                pos[u], pos[v],
                arrowstyle='->',
                connectionstyle=f'arc3,rad={self_loop_rad}',
                color='gray',
                linewidth=1.5
            )
            ax.add_patch(arrow)
        else:
            # 普通边:直接绘制箭头
            arrow = FancyArrowPatch(
                pos[u], pos[v],
                arrowstyle='->',
                color='gray',
                linewidth=1.5
            )
            ax.add_patch(arrow)

# 使用示例
fig, ax = plt.subplots(figsize=(8, 6))
pos = nx.spring_layout(G, seed=42)
draw_network(G, pos, ax)

# 设置坐标轴范围,避免图形被裁剪
ax.set_xlim(-1.2, 1.2)
ax.set_ylim(-1.2, 1.2)
plt.axis('off')
plt.show()
总结

优先使用NetworkX的原生绘图函数,因为它已经处理了自环、节点标签、布局等各种边界情况,比自己写函数高效且不易出错。基于邻接矩阵构建图用nx.from_numpy_array()即可一步到位,完全满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 10:30:18