使用networkx在两个节点之间绘制多个边

时间:2014-04-01 12:25:38

标签: python graph networkx labels edge

我需要绘制一个在两个节点之间具有多个边(具有不同权重)的有向图。也就是说,我有节点A和B以及长度= 2的边(A,B)和长度= 3的(B,A)。

我尝试过使用G = nx.Digraph和G = nx.Multidigraph。当我绘制它时,我只能查看一个边缘而只能看到其中一个标签。 有没有办法做到这一点?

6 个答案:

答案 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()

See here the result

答案 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()

这将返回此图形,其中包含两条边和边缘上显示的长度:

enter image description here

答案 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);

enter image description here

答案 3 :(得分:0)

有关使用networkx绘制多个边缘以获取图形的信息,请参见此处,如示例所示:https://github.com/pdzx/multi-edges

example

答案 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位置相同,则标签不会显示。

plot with edge labels

答案 5 :(得分:0)

enter image description here

在两个节点之间绘制双向边的常用方法有两种:

  1. 将两条边绘制为直线,每条边都与连接节点的直线平行但略有偏移。
  2. 将两条边绘制成曲线;确保它们在不同的方向上呈弧形。 在这两种情况下,标签都可以简单地放置在两条线的中心。

这两种方法都不能很好地适应 networkx 绘图实用程序的当前状态:

  1. 第一种方法需要在 平行边。其他库中的常见选择包括 平均边缘宽度或节点大小的三分之一。然而,节点 networkx 中的位置在数据坐标中给出,而节点 尺寸和边缘宽度在显示坐标中给出。这使得 偏移量的计算很麻烦,而且——更重要的是—— 如果调整图形大小,布局会中断(作为转换 从数据坐标到显示坐标的变化)。

  2. 如其他答案所述,networkx 可以通过 设置正确的 connectionstyle。然而,这个功能被 最近添加到 networkx 中,因此功能 绘制标签仍然假设直边。如果只有边缘 有一个非常小的弧度(即仍然基本上是直的),那么 可以通过添加将标签伪造到近似正确的位置 标签正确位置的换行符,如 @PaulMenzies 的回答证明了这一点。然而,这种做法 如果曲率是,通常会产生次优结果并中断 高。

如果您愿意使用其他基于 matplotlib 构建的绘图实用程序, 我在我的模块中实现了这两种方法 netgraphnetgraph 是 与 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()