我需要绘制一个在两个节点之间具有多个边(具有不同权重)的有向图。也就是说,我有节点A和B以及长度= 2的边(A,B)和长度= 3的(B,A)。
我尝试过使用G = nx.Digraph和G = nx.Multidigraph。当我绘制它时,我只能查看一个边缘而只能看到其中一个标签。 有没有办法做到这一点?
答案 0 :(得分:12)
对上述答复的改进是在nx.draw中添加了connectionstyle,这可以看到图中的两条平行线:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph() #or G = nx.MultiDiGraph()
G.add_node('A')
G.add_node('B')
G.add_edge('A', 'B', length = 2)
G.add_edge('B', 'A', length = 3)
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, connectionstyle='arc3, rad = 0.1')
edge_labels=dict([((u,v,),d['length'])
for u,v,d in G.edges(data=True)])
plt.show()
答案 1 :(得分:10)
尝试以下方法:
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph() #or G = nx.MultiDiGraph()
G.add_node('A')
G.add_node('B')
G.add_edge('A', 'B', length = 2)
G.add_edge('B', 'A', length = 3)
pos = nx.spring_layout(G)
nx.draw(G, pos)
edge_labels=dict([((u,v,),d['length'])
for u,v,d in G.edges(data=True)])
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, label_pos=0.3, font_size=7)
plt.show()
这将返回此图形,其中包含两条边和边缘上显示的长度:
答案 2 :(得分:1)
您可以使用已计算的节点位置直接使用matplotlib。
/* libcurl will internally think that you connect to the host
* and port that you specify in the URL option. */
curl_easy_setopt(curl, CURLOPT_URL, "http://99.99.99.99:9999");
/* call this function to get a socket */
curl_easy_setopt(curl, CURLOPT_OPENSOCKETFUNCTION, opensocket);
curl_easy_setopt(curl, CURLOPT_OPENSOCKETDATA, &sockfd);
/* call this function to set options for the socket */
curl_easy_setopt(curl, CURLOPT_SOCKOPTFUNCTION, sockopt_callback);
res = curl_easy_perform(curl);
curl_easy_cleanup(curl);
答案 3 :(得分:0)
有关使用networkx绘制多个边缘以获取图形的信息,请参见此处,如示例所示:https://github.com/pdzx/multi-edges
答案 4 :(得分:0)
在AMangipinto的解决方案中添加以下代码,以在两个方向上添加边缘标签(请参阅图片链接):
edge_labels = dict([((u, v,), f'{d["length"]}\n\n{G.edges[(v,u)]["length"]}')
for u, v, d in G.edges(data=True) if pos[u][0] > pos[v][0]])
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_color='red')
“ if pos [u] [0]> pos [v] [0]”仅在一个方向上添加边缘标签。我们将两个长度都添加到单个标签上,否则我们将在边缘上覆盖第一个标签。 注意:如果节点的x位置相同,则标签不会显示。
答案 5 :(得分:0)
在两个节点之间绘制双向边的常用方法有两种:
这两种方法都不能很好地适应 networkx
绘图实用程序的当前状态:
第一种方法需要在
平行边。其他库中的常见选择包括
平均边缘宽度或节点大小的三分之一。然而,节点
networkx
中的位置在数据坐标中给出,而节点
尺寸和边缘宽度在显示坐标中给出。这使得
偏移量的计算很麻烦,而且——更重要的是——
如果调整图形大小,布局会中断(作为转换
从数据坐标到显示坐标的变化)。
如其他答案所述,networkx
可以通过
设置正确的 connectionstyle
。然而,这个功能被
最近添加到 networkx 中,因此功能
绘制标签仍然假设直边。如果只有边缘
有一个非常小的弧度(即仍然基本上是直的),那么
可以通过添加将标签伪造到近似正确的位置
标签正确位置的换行符,如
@PaulMenzies 的回答证明了这一点。然而,这种做法
如果曲率是,通常会产生次优结果并中断
高。
如果您愿意使用其他基于 matplotlib
构建的绘图实用程序,
我在我的模块中实现了这两种方法
netgraph。 netgraph
是
与 networkx 和 igraph Graph 对象完全兼容,因此它应该
轻松快速地生成美观的图表。
#!/usr/bin/env python
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
from netgraph import Graph # pip install netgraph
triangle = nx.DiGraph([('a', 'b'), ('a', 'c'), ('b', 'a'), ('c', 'b'), ('c', 'c')])
node_positions = {
'a' : np.array([0.2, 0.2]),
'b' : np.array([0.8, 0.2]),
'c' : np.array([0.5, 0.8]),
}
edge_labels = {
('a', 'b') : 3,
('a', 'c') : 'Lorem ipsum',
('b', 'a') : 4,
('c', 'b') : 'dolor sit',
('c', 'c') : r'$\pi$'
}
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(14,14))
Graph(triangle, node_labels=True, edge_labels=edge_labels,
edge_label_fontdict=dict(size=12, fontweight='bold'),
node_layout=node_positions, edge_layout='straight',
node_size=6, edge_width=4, arrows=True, ax=ax1)
Graph(triangle, node_labels=True, edge_labels=edge_labels,
edge_label_fontdict=dict(size=12, fontweight='bold'),
node_layout=node_positions, edge_layout='curved',
node_size=6, edge_width=4, arrows=True, ax=ax2)
plt.show()