在Python3中使用NetworkX创建曲线边

在Python3中使用NetworkX创建曲线边,python,matplotlib,graph,networkx,directed-graph,Python,Matplotlib,Graph,Networkx,Directed Graph,我想使用networkx(如果您知道更好的框架,我还想使用另一个框架)来创建 节点位于固定位置的图形。同时,图形的边不应重叠 我以前的代码如下所示: #!/usr/bin/env python3 import networkx as nx import matplotlib.pyplot as plt # Graph data names = ['A', 'B', 'C', 'D', 'E'] positions = [(0, 0), (0, 1), (1, 0), (0.5, 0.5),

我想使用networkx(如果您知道更好的框架,我还想使用另一个框架)来创建 节点位于固定位置的图形。同时,图形的边不应重叠

我以前的代码如下所示:

#!/usr/bin/env python3

import networkx as nx
import matplotlib.pyplot as plt

# Graph data
names = ['A', 'B', 'C', 'D', 'E']
positions = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1, 1)]
edges = [('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('D', 'A')]

# Matplotlib figure
plt.figure('My graph problem')

# Create graph
G = nx.MultiDiGraph(format='png', directed=True)

for index, name in enumerate(names):
    G.add_node(name, pos=positions[index])

labels = {}
for edge in edges:
    G.add_edge(edge[0], edge[1])
    labels[(edge[0], edge[1])] = '{} -> {}'.format(edge[0], edge[1])

layout = dict((n, G.node[n]["pos"]) for n in G.nodes())
nx.draw(G, pos=layout, with_labels=True, node_size=300)
nx.draw_networkx_edge_labels(G, layout, edge_labels=labels)

plt.show()
并给出以下结果


如何确保边是“圆形”的,这样它们就不会重叠?

正如Paul提到的,现在可以在
draw\u networkx\u Edge
中选择使用
FancyArrowPatch
,尽管它只适用于有向图,而且速度非常慢

值得一提的是,我打包了一些旧代码,使用
bezier
包从NetworkX图形(或任何边列表)生成漂亮的曲线边,并绘制它们。它可能有用:

使用dataset和ForceAtlas2布局的示例图像:


我认为不能直接使用networkx函数来实现这一点。但是,可以直接使用已计算的节点位置使用matplotlib

调整代码:

 import networkx as nx
import matplotlib.pyplot as plt

# Graph data
names = ['A', 'B', 'C', 'D', 'E']
positions = [(0, 0), (0, 1), (1, 0), (0.5, 0.5), (1, 1)]
edges = [('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('D', 'A')]

# Matplotlib figure
plt.figure('My graph problem')

# Create graph
G = nx.MultiDiGraph(format='png', directed=True)

for index, name in enumerate(names):
    G.add_node(name, pos=positions[index])

labels = {}




layout = dict((n, G.node[n]["pos"]) for n in G.nodes())
nx.draw(G, pos=layout, with_labels=True, node_size=300)
ax = plt.gca()
for edge in edges:
    ax.annotate("",
                xy=layout[edge[0]], xycoords='data',
                xytext=layout[edge[1]], textcoords='data',
                arrowprops=dict(arrowstyle="->", color="0.5",
                                shrinkA=5, shrinkB=5,
                                patchA=None, patchB=None,
                                connectionstyle="arc3,rad=-0.3",
                                ),
                )
plt.show()
给出:


另请参见。

在其他NetworkX新闻中,您现在可以指定一个
connectionstyle
参数
nx。绘制网络X\u边
。例如,如果我想要一个具有曲线边的网络,我可以写:

# Compute position of nodes
pos = nx.kamada_kawai_layout(G)

# Draw nodes and edges
nx.draw_networkx_nodes(G, pos)
nx.draw_networkx_edges(
    G, pos,
    connectionstyle="arc3,rad=0.1"  # <-- THIS IS IT
)
#计算节点的位置
位置=nx.kamada_kawai_布局图(G)
#绘制节点和边
nx.绘制网络x\u节点(G、pos)
nx.draw_网络x_边(
G、 pos,
connectionstyle=“arc3,rad=0.1”#
图表的边不应重叠

使用
connectionstyle
参数以预先确定的曲率绘制圆弧不会减少边或节点边重叠

对于直边,与其他绘图元素的重叠通常是不可避免的。但是,如果允许我们绘制曲线边,我们可以对每条边进行布线,以尽可能避免其他节点和边。可以通过在每条边中插入控制点,有效地将每条边分割为短子边来实现此效果。我们可以然后使用标准的Fruchterman-Reingold算法(在
networkx
中称为
spring\u布局
)将图形模拟为一个弹簧系统,其中所有节点和控制点相互排斥,但连接的节点和控制点也相互吸引节点保持固定,同时我们让边缘控制点的位置退火到其平衡位置

我有一个这种方法的实现。该代码是名为netgraph的python网络绘图库的一部分,我是该库的作者。
netgraph
与networkx和igraph图形对象完全兼容,因此生成美观的图形应该是简单而快速的


很抱歉,这里无法提供帮助;以下setup.py导致代码出现segfault。Cairocfi==0.9.0 cffi==1.11.5 cycler==0.10.0 decorator==4.3.0 kiwisolver==1.0.1 matplotlib==3.0.0 networkx==2.2 numpy==1.15.2 pgi==0.11.2 pycparser==2.19 pycparser==2.2.2.2.2.2.2.2 dateutil==2.7.3 six==1.11.0 wou你介意分享你的吗?注释格式是最糟糕的-。-“只需执行一个pip安装networkx&&pip安装matplotlib谢谢,我想这是出于好意。但不是我需要的。我以前按照你的建议做了,它缺少几个依赖项。安装它们后,我会遇到segfaults。这不是我想要调试的,所以如果你可以复制安装程序。py如果您成功地使用,可能会有人帮助您,而不会遇到与我相同的问题。当您使用时,您使用的是哪种特定的python版本?3.5、3.6或3.7?AFAIK,目前无法使用
networkx
绘制带曲线边的图形,尽管修改源代码并不太困难。
networkx
使用matplotlib中的
FancyRowPatch
类在
绘制网络X\u边
中绘制箭头(由
绘制
包裹).
FancyRowPatch
支持
connectionstyle
参数,该参数不是由
draw\u networkx\u Edge
设置的;默认值是一条直线,这是您目前得到的。鉴于MWE的质量,我怀疑您将设法克隆
networkx
github repo和patch
draw\u networkx\u Edge
。刚刚尝试将
connectionstyle='arc3,rad=0.1'
传递到
nx.draw()
,它在一个小(ish)图上非常适合我的用例。刚刚尝试了Colab,结果是,
多向图
实现发生了变化。我不得不使用
节点
(复数)而不是下一行中的
node
layout=dict((n,G.nodes[n][“pos”])代表n in G.nodes())
(我还应该说,出于某种原因,这似乎只在边缘定向时起作用。这肯定是一个bug,当某个正派的人提出问题并对其进行PR时,它可能会得到修复
#!/usr/bin/env python
import matplotlib.pyplot as plt
import networkx as nx

from netgraph import Graph # pip install netgraph

g = nx.florentine_families_graph()
Graph(g, edge_layout='curved')
plt.show()