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

使用Networkx绘制图时为指定边添加方向箭头

为NetworkX无向图指定边添加箭头的实现方案

完全可以实现仅为Edges列表内特定边添加箭头的效果,不需要将整图转换为有向图,拆分边的绘制逻辑即可达成目标。

核心实现逻辑

nx.draw_networkx_edges方法原生支持箭头显示控制:

  • 传入arrows=True即可为当前批次绘制的边添加方向箭头
  • 箭头方向由边元组的顺序决定:元组(u, v)代表箭头从节点u指向节点v
  • 可通过arrowsize、arrowstyle参数调整箭头大小、样式,和边宽、配色效果适配
  • 将需要加箭头的边、不需要加箭头的边分两个批次调用绘制方法,即可实现仅部分边带箭头的效果

注意:无向图的边是无序存储的,如果边列表内的元组顺序和你定义的带箭头边元组顺序不一致(比如边存为(3,1),要添加的箭头方向为1→3),匹配时可以将边转为frozenset做判断,避免漏绘。

修改后的可运行代码

import networkx as nx
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.cm import ScalarMappable

N = 1

def pos():
    x, y = 1, N + 3 - 1
    for _ in range(2 * N * (N + 1)):
        yield (x, y)
        y -= (x + 2) // (N + 3)
        x = (x + 2) % (N + 3)

G = nx.Graph()
it_pos = pos()
for u in range(2 * N * (N + 1)):
    G.add_node(u + 1, pos=next(it_pos))
    if u % (2 * N + 1) < N:
        for v in (u - 2 * N - 1, u - N - 1, u - N):
            if G.has_node(v + 1):
                G.add_edge(u + 1, v + 1)
    elif u % (2 * N + 1) == N:
        G.add_edge(u + 1, u - N + 1)
    elif u % (2 * N + 1) < 2 * N:
        for v in (u - 1, u - N - 1, u - N):
            G.add_edge(u + 1, v + 1)
    else:
        for v in (u - 1, u - N - 1):
            G.add_edge(u + 1, v + 1)

# 绘制基础图的节点、标签、默认样式边
pos = nx.get_node_attributes(G, 'pos')
nx.draw(G, pos, with_labels=True, font_weight='bold')

Edges=np.array([[1,2],[1,3],[1,4]])
Weights=np.array([[1.7],[2.9],[8.6]])
flat_weights = Weights.flatten()
weights_normalized = [x / max(flat_weights) for x in flat_weights]
edge_weight_map = dict(zip([tuple(e) for e in Edges.tolist()],weights_normalized))
my_cmap = plt.cm.get_cmap('Oranges')

# 自定义配置:需要添加箭头的边,元组顺序即为箭头方向
arrow_edges = [(1,3), (1,4)]
# 筛选出同批次着色但不需要加箭头的边
non_arrow_edges = [e for e in [tuple(x) for x in Edges.tolist()] if e not in arrow_edges]

# 绘制不带箭头的着色边
non_arrow_colors = my_cmap([edge_weight_map[e] for e in non_arrow_edges])
nx.draw_networkx_edges(G, pos, edge_color=non_arrow_colors,
                       edgelist=non_arrow_edges, width=5)

# 绘制带箭头的着色边,调整箭头大小匹配边宽
arrow_colors = my_cmap([edge_weight_map[e] for e in arrow_edges])
nx.draw_networkx_edges(G, pos, edge_color=arrow_colors,
                       edgelist=arrow_edges, width=5,
                       arrows=True, arrowsize=20, arrowstyle='->')

# 绘制色阶条
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(0,max(flat_weights)))
plt.colorbar(sm)
plt.show()

自定义调整说明

  • 原有边的权重映射着色逻辑完全保留,不会影响颜色和权重的对应关系
  • 仅需要修改arrow_edges列表内容,即可自定义哪些边需要加箭头、箭头的指向
  • 调整arrowsize参数数值可以放大/缩小箭头,适配不同边宽下的视觉效果

效果参考

  • 原代码运行输出效果:
    原代码运行效果
  • 预期实现效果:
    预期实现效果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 10:06:20