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

如何用Python创建带平行边的有向加权图并解决NetworkX可视化报错

问题描述

我正在开展一个项目,需要用Python创建支持节点间带不同权重平行边的有向加权图,目前使用networkx库和Matplotlib进行可视化。

我的目标:

  • 创建带有平行边(同一节点间多条边)的有向图;
  • 为这些边分配随机权重;
  • 可视化该图并显示带权重的边标签。

我编写的代码:

import random
import networkx as nx
import matplotlib.pyplot as plt

def create_graph(n_nodes, alpha = 0.5):
    G = nx.MultiDiGraph()
    G.add_nodes_from(range(n_nodes))
    for i in range(n_nodes):
        for j in range(i+1,n_nodes):
            if random.random() < alpha:
                weight=random.randint(1,10)
                G.add_edge(i, j, weight=weight)

            if random.random() < alpha:
                weight=random.randint(1,10)
                G.add_edge(j, i, weight=weight)
    return G
  

def display_graph(G):
    pos = nx.spring_layout(G)  
    weight_labels = nx.get_edge_attributes(G, 'weight')  
    nx.draw(G, pos, with_labels=True, node_color='skyblue', edge_color='gray', node_size=700)
    nx.draw_networkx_edge_labels(G, pos, edge_labels=weight_labels)  
    plt.show()


n_nodes = 5
G = create_graph(n_nodes, alpha = 0.5)
display_graph(G)

运行时出现错误:

networkx.exception.NetworkXError: draw_networkx_edge_labels does not support multiedges.

我需要解决两个问题:

  1. 如何解决该错误,正确可视化带平行边的有向加权图?
  2. 在networkx中有没有更好的创建和可视化带平行边的有向图的方法?
解决方案

问题1:修复可视化边标签的错误

draw_networkx_edge_labels不支持MultiDiGraph的核心原因是它无法区分平行边的唯一键(key)。要解决这个问题,需要手动遍历每条包含键信息的边,计算标签位置并绘制。

修改后的display_graph函数如下:

def display_graph(G):
    pos = nx.spring_layout(G)  
    # 绘制节点和边,用弧形显示平行边避免重叠
    nx.draw(G, pos, with_labels=True, node_color='skyblue', edge_color='gray', node_size=700, connectionstyle='arc3,rad=0.1')
    
    # 手动绘制每条边的权重标签
    for u, v, key, weight in G.edges(data='weight', keys=True):
        # 计算边的中间位置
        x_u, y_u = pos[u]
        x_v, y_v = pos[v]
        x_mid = (x_u + x_v) / 2
        y_mid = (y_u + y_v) / 2
        # 根据边的键值添加偏移,避免平行边标签重叠
        offset = 0.05 * key
        # 按边的方向调整偏移方向
        if x_u < x_v:
            x_mid += offset
        else:
            x_mid -= offset
        if y_u < y_v:
            y_mid += offset
        else:
            y_mid -= offset
        # 绘制带背景的标签,提升可读性
        plt.text(x_mid, y_mid, str(weight), fontsize=10, ha='center', va='center', bbox=dict(facecolor='white', edgecolor='none', alpha=0.7))
    
    plt.show()

关键改动说明:

  • 用connectionstyle='arc3,rad=0.1'让平行边以弧形展示,避免直线重叠;
  • 遍历边时带上keys=True,获取每条平行边的唯一标识;
  • 给不同键的标签设置不同偏移量,确保标签不重叠;
  • 用plt.text替代不支持多图的draw_networkx_edge_labels,手动绘制标签。

问题2:NetworkX中创建和可视化平行边有向图的优化方法

创建图的优化

你的create_graph函数逻辑没问题,可以简化为更清晰的写法,效果和原代码一致:

def create_graph(n_nodes, alpha=0.5):
    G = nx.MultiDiGraph()
    G.add_nodes_from(range(n_nodes))
    # 生成所有有序节点对(i≠j)
    node_pairs = [(i,j) for i in range(n_nodes) for j in range(n_nodes) if i != j]
    for u, v in node_pairs:
        if random.random() < alpha:
            G.add_edge(u, v, weight=random.randint(1,10))
    return G

可视化的进阶技巧

可以通过分组绘制平行边,给不同边设置不同颜色和弧度,提升区分度:

def display_graph_advanced(G):
    pos = nx.spring_layout(G, seed=42)  # 固定种子保证布局稳定
    # 绘制节点和节点标签
    nx.draw_networkx_nodes(G, pos, node_color='skyblue', node_size=700)
    nx.draw_networkx_labels(G, pos, font_size=12)
    
    # 给不同键的平行边设置不同弧度和颜色
    edge_rad_map = {0: 0.1, 1: -0.1, 2: 0.2}  # 可根据实际边数调整
    for key in set(k for _,_,k in G.edges):
        # 筛选当前键对应的所有边
        edges = [(u, v) for u, v, k in G.edges if k == key]
        rad = edge_rad_map.get(key, 0.05 * key)
        # 绘制当前组的边
        nx.draw_networkx_edges(G, pos, edgelist=edges, connectionstyle=f'arc3,rad={rad}', edge_color=f'C{key}', arrowsize=20)
        
        # 绘制当前组边的标签
        for u, v, k, weight in G.edges(data='weight', keys=True):
            if k == key:
                x_mid = (pos[u][0] + pos[v][0])/2 + 0.08*rad
                y_mid = (pos[u][1] + pos[v][1])/2 + 0.08*rad
                plt.text(x_mid, y_mid, str(weight), fontsize=10, bbox=dict(facecolor='white', alpha=0.8))
    
    plt.box(False)
    plt.show()

这个版本的优势:

  • 固定布局种子,每次运行的图结构一致,方便调试;
  • 不同平行边用不同颜色和弧度区分,视觉更清晰;
  • 标签位置和边的弧度对应,排版更协调。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 04:35:39