使用Networkx根据矩阵构建含无向与有向边的混合图
NetworkX混合有向/无向边图实现方案
核心实现逻辑
NetworkX没有原生支持同时包含有向边、无向边的混合图类型,最简便的落地方案是用DiGraph(有向图)作为基础承载结构:
- 对矩阵取值为2的有向边:仅添加行索引指向列索引的单向边,给边添加
edge_type属性标记为directed - 对矩阵取值为1的无向边:添加正反两个方向的边,标记为
undirected,绘制时隐藏这类边的箭头,视觉上就和普通无向边完全一致 - 两类边分开传参给绘图函数,分别设置箭头、颜色等样式做区分
完整可运行代码
import numpy as np import networkx as nx import matplotlib.pyplot as plt # 输入目标邻接矩阵 adj_matrix = np.matrix([[0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [2, 0, 0, 0, 0, 0, 0, 1], [0, 0, 0, 0, 0, 1, 0, 0], [0, 0, 0, 0, 0, 0, 2, 1], [0, 0, 0, 1, 0, 0, 2, 0], [2, 2, 0, 0, 0, 0, 0, 0], [0, 0, 1, 0, 1, 0, 0, 0]]) # 初始化有向图容器 G = nx.DiGraph() # 加入全部8个节点,默认使用和矩阵一致的0基索引;如果需要1基编号(匹配举例的1->6格式),把range(8)替换为range(1,9),后续添加边时i、j各加1即可 G.add_nodes_from(range(8)) # 遍历矩阵解析边 for i in range(adj_matrix.shape[0]): for j in range(adj_matrix.shape[1]): val = adj_matrix[i, j] if val == 2: # 添加行i指向列j的有向边 G.add_edge(i, j, edge_type='directed') elif val == 1: # 无向边仅在i<j时处理,避免重复添加双向边 if i < j: G.add_edge(i, j, edge_type='undirected') G.add_edge(j, i, edge_type='undirected') # 拆分两类边列表,用于分别设置绘图样式 directed_edge_list = [(u, v) for u, v, attr in G.edges(data=True) if attr['edge_type'] == 'directed'] undirected_edge_list = [(u, v) for u, v, attr in G.edges(data=True) if attr['edge_type'] == 'undirected'] # 执行绘制 pos = nx.spring_layout(G, seed=42) # 固定随机种子保证布局可复现,可替换为circular_layout等其他布局 nx.draw_networkx_nodes(G, pos, node_size=500, node_color='#a6d9f7') nx.draw_networkx_labels(G, pos, font_size=10) # 绘制有向边:显示箭头,深色 nx.draw_networkx_edges(G, pos, edgelist=directed_edge_list, edge_color='#222f3e', arrows=True, arrowstyle='->', arrowsize=20, width=2) # 绘制无向边:隐藏箭头,浅灰色 nx.draw_networkx_edges(G, pos, edgelist=undirected_edge_list, edge_color='#8395a7', arrows=False, width=2) plt.axis('off') plt.show()
效果说明
- 深色带箭头的边完全匹配规则中取值为2的有向边,指向为行索引到列索引
- 浅灰色无箭头的边匹配取值为1的无向边,视觉效果和普通无向图边一致
- 可以自行调整节点大小、颜色、边宽、布局算法等参数适配自己的展示需求
内容的提问来源于stack exchange,提问作者Batman23
相关产品推荐
相关产品推荐

