在Python/NetworkX有向图中,如何分离边缘箭头?

4

我想要获得类似于这个的东西:

enter image description here

使用Python库networkx,我可以使用以下代码生成类似的有向图:

import matplotlib.pyplot as plt
import networkx as nx

G = nx.DiGraph()

G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')

nx.draw(G, node_color='w', edgecolors='k', width=2.0, with_labels=True)
plt.show()

这将会产生:

enter image description here

然而,节点3和4之间的箭头重叠在一起,看起来只是一个带有两个头的单一箭头。是否可能稍微分开它们,以更明显地表明那里有两个边缘而不仅仅是一个?(我知道可以使用pygraphviz来完成此操作,但我正在尝试使用matplotlib完成它。)
2个回答

1
我一段时间前fork了networkx绘图工具来解决这个问题和其他几个问题。该包名为netgraph,支持绘制networkxigraph图结构(以及简单的边缘列表)。它在底层使用matplotlib,并公开创建的艺术家,使得即使没有内置功能来操作它们,也很容易进一步操纵它们。
#!/usr/bin/env python

"""
https://dev59.com/o7roa4cB1Zd3GeqPm5LU
"""

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

G = nx.DiGraph()

G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')

netgraph.draw(G, node_color='w', edge_color='k', edge_width=2.0, node_labels={str(ii) : str(ii) for ii in range(1,5)})
plt.show()

enter image description here


哇!我终于转向了pygraphviz,因为它在图形布局方面提供了更多的控制(甚至有点过头了...),但我刚刚检查了你的库,我必须说你做得很好!所以,即使最终我可能不会使用它,这个答案肯定回答了我的问题! - Tropilio
@Tropilio 如果您不介意我问一下,是什么阻止了您使用netgraph?我想知道在哪些方面需要改进这个项目。 - Paul Brodersen
坦白说,我还没有足够的时间测试netgraph来回答这个问题。几天前,我转而使用pygraphviz,因为“neato”布局已经几乎适合我的目的。现在我正在尝试使用pygraphviz获得良好的结果,但如果您能给我一些关于如何使用netgraph实现这一点的建议,我会尝试一下。 - Tropilio
绘制图形有两个部分。1)计算节点位置的布局(可能还包括边路径),和2)在画布上实际绘制节点和边缘。netgraph 关注于第二步,允许您通过 node_positions 参数指定节点位置。因此,您可以使用 networkx.drawing.nx_pydot.graphviz_layout 计算出一个 graphviz/neato 节点布局,然后将其传递给 netgraph。 - Paul Brodersen

1
你需要一个MultiDiGraph来处理两个节点之间的多条边:
G = nx.MultiDiGraph()

G.add_edge('1','2')
G.add_edge('1','3')
G.add_edge('3','2')
G.add_edge('3','4')
G.add_edge('4','3')

要想可视化网络,您可以使用Graphviz,它可以显示并行边缘。您可以使用dot编写图形,并使用graphviz.Source来显示图形:

from networkx.drawing import nx_pydot
from graphviz import Source

nx_pydot.write_dot(G, 'multig.dot')
Source.from_file('multig.dot')

enter image description here


谢谢你的回答!但是不幸的是这并没有解决我的问题...正如我在问题中所述,我正在尝试使用matplotlib绘图。 - Tropilio
1
据我所知,对于多重图,您将需要使用 graphviz @Tropilio。 - yatu
pygraphviz_layout,但是我尝试过几次,它只是重叠了所有平行边 @Tropilio - yatu
1
是的,我刚试了一下,基本上没有看到什么区别...不管怎样,感谢您的建议。 - Tropilio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接