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

如何用NetworkX绘制带权双向多重图?解决边双向性与不显示问题

问题解决步骤

1. 替换图类型以支持多边

NetworkX的普通DiGraph/Graph不支持平行边(同一节点对的多条边),会自动覆盖重复边,所以必须改用MultiDiGraph(支持有向多边)或MultiGraph(支持无向多边),才能保存并显示多条边。

2. 满足节点边数要求

按照需求给节点1与2、1与3添加至少3条边:

  • 无向图:直接给节点对(1,2)、(1,3)各加3条边
  • 双向有向图:给(1,2)和(2,1)、(1,3)和(3,1)各加3条边

3. 调整绘制逻辑避免多边重叠

给同节点对的每条边分配不同弧度,让它们分散显示,不会重叠在一起。


完整修正代码

方案一:无向多边图(MultiGraph)

import networkx as nx
import matplotlib.pyplot as plt

# 使用支持多边的无向图结构
G = nx.MultiGraph()
# 给1-2、1-3各添加3条带权重的边
edge_list = [
    (1, 2, {'w': 'A1'}), (1, 2, {'w': 'A2'}), (1, 2, {'w': 'A3'}),
    (1, 3, {'w': 'B1'}), (1, 3, {'w': 'B2'}), (1, 3, {'w': 'B3'})
]
G.add_edges_from(edge_list)

# 固定布局种子保证节点位置一致
pos = nx.spring_layout(G, seed=5)
fig, ax = plt.subplots()

# 绘制节点和标签
nx.draw_networkx_nodes(G, pos, ax=ax)
nx.draw_networkx_labels(G, pos, ax=ax)

# 分组处理同节点对的多边,分配不同弧度
edge_groups = {}
for u, v, key in G.edges(keys=True):
    # 无向图中(u,v)和(v,u)是同一组
    group_key = tuple(sorted((u, v)))
    if group_key not in edge_groups:
        edge_groups[group_key] = []
    edge_groups[group_key].append((u, v, key))

for group, edges in edge_groups.items():
    num_edges = len(edges)
    # 给每条边分配从-0.3到0.3的分散弧度
    rads = [i * 0.6 / (num_edges - 1) - 0.3 for i in range(num_edges)]
    for i, (u_e, v_e, key) in enumerate(edges):
        nx.draw_networkx_edges(
            G, pos, ax=ax,
            edgelist=[(u_e, v_e)],
            connectionstyle=f'arc3, rad={rads[i]}'
        )

# 绘制边权重标签
nx.draw_networkx_edge_labels(G, pos, edge_labels={(u, v, key): d['w'] for u, v, key, d in G.edges(data=True, keys=True)})
plt.show()

方案二:双向有向多边图(MultiDiGraph)

import networkx as nx
import matplotlib.pyplot as plt

# 使用支持多边的有向图结构
G = nx.MultiDiGraph()
# 给1→2、2→1、1→3、3→1各添加3条带权重的边
edge_list = [
    (1, 2, {'w': 'A1'}), (1, 2, {'w': 'A2'}), (1, 2, {'w': 'A3'}),
    (2, 1, {'w': 'A4'}), (2, 1, {'w': 'A5'}), (2, 1, {'w': 'A6'}),
    (1, 3, {'w': 'B1'}), (1, 3, {'w': 'B2'}), (1, 3, {'w': 'B3'}),
    (3, 1, {'w': 'B4'}), (3, 1, {'w': 'B5'}), (3, 1, {'w': 'B6'})
]
G.add_edges_from(edge_list)

pos = nx.spring_layout(G, seed=5)
fig, ax = plt.subplots()

# 绘制节点和标签
nx.draw_networkx_nodes(G, pos, ax=ax)
nx.draw_networkx_labels(G, pos, ax=ax)

# 处理同方向多边的弧度,反向边用负弧度避免重叠
edge_pairs = {}
for u, v, key in G.edges(keys=True):
    if (u, v) not in edge_pairs:
        edge_pairs[(u, v)] = []
    edge_pairs[(u, v)].append((u, v, key))

for (u, v), edges in edge_pairs.items():
    num_edges = len(edges)
    rads = [i * 0.2 for i in range(num_edges)]
    # 反向边用负弧度,和正向边区分开
    if (v, u) in edge_pairs:
        rads = [-r for r in rads]
    for i, (u_e, v_e, key) in enumerate(edges):
        nx.draw_networkx_edges(
            G, pos, ax=ax,
            edgelist=[(u_e, v_e)],
            connectionstyle=f'arc3, rad={rads[i]}',
            arrowstyle='->'
        )

# 绘制边权重标签
nx.draw_networkx_edge_labels(G, pos, edge_labels={(u, v, key): d['w'] for u, v, key, d in G.edges(data=True, keys=True)})
plt.show()

关键问题说明
  • 多边不显示的根源:原代码使用的DiGraph不支持平行边,重复添加的边会被覆盖,改用MultiDiGraph/MultiGraph才能存储多条边。
  • 双向/无向实现:无向图直接用MultiGraph,所有边默认双向;如果需要明确的双向有向边,用MultiDiGraph并给每个方向都添加足够数量的边。
  • 多边可视化:通过给每条同节点对的边分配不同弧度,避免重叠,确保所有边都能被看到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 17:27:03