在SPYDER中用Python绘制有向图

5 投票
2 回答
2873 浏览
提问于 2025-04-17 23:28

我正在使用SPYDER,下面是我的代码。这个代码可以生成图形,但图形看起来不太清晰。我希望在图中看到不同的层次——第一层有一个“开始”节点,第二层有1、2、3这几个节点,第三层有“a”、“b”、“c”这几个节点,最后一层有一个“结束”节点。有没有什么办法可以实现我的目标呢?

import networkx as nx
import matplotlib.pyplot as plt
import os.path as path

G=nx.DiGraph()
G.add_nodes_from(['start',1,2,3,'a','b','c','end'])

G.nodes(data=True)

G.add_edge('start',2)
G.add_edge('start',3)
G.add_edge(2,'b')
G.add_edge('b','end')
G.add_edge('a','end')
G.add_edge('f','g')
nx.draw(G)

------------------------更新------------------

我所说的层次是指我希望网络的展示方式像附图那样。我想要这样的网络图,因为在某一层的节点只会直接连接到上一层或下一层的节点。

在这里输入图片描述

2 个回答

2

你至少有两个选择:如果你愿意,可以自己创建一个字典来保存节点的位置。首先,把节点分配到不同的层级,然后:

position = dict()
for (i, layer) in enumerate(layers):
    for (j, node) in enumerate(layer):
        position[node] = (i, j / float(len(layer))

接着,你可以用给定的节点位置来绘制网络,使用的代码是 nx.draw(G, pos=position)

另一个选择是使用 graphviz 和 Python 的 AGraph 类,这样可以生成分层的布局。

5

看起来 networkx 对于图的排列功能支持得不多,不过我只用过几次,所以不能确定。我找不到实现你所要求功能的方法。

不过,我尝试使用 graphviz(这个需要先安装)来实现这个功能。关于排名方法的来源可以参考 这个StackOverflow的回答

复制粘贴示例

import networkx as nx

ranked_node_names = [['start'],
                     [1, 2, 3],
                     ['a', 'b', 'c'],
                     ['end']]
node_edges = [('start', 2),
              ('start', 3),
              (2, 'b'),
              ('b', 'end'),
              ('a', 'end')]

# graph and base nodes/edges in networkx
G = nx.DiGraph()
for rank_of_nodes in ranked_node_names:
    G.add_nodes_from(rank_of_nodes)
G.nodes(data=True)
G.add_edges_from(node_edges)
# I don't know a way to automatically arrange in networkx so using graphviz
A = nx.to_agraph(G)
A.graph_attr.update(rankdir='LR')  # change direction of the layout
for rank_of_nodes in ranked_node_names:
    A.add_subgraph(rank_of_nodes, rank='same')
# draw
A.draw('example.png', prog='dot')

默认输出

在这里输入图片描述

LR(左到右)输出

在这里输入图片描述

撰写回答