如何改进networkx杠铃图的布局?

问题描述

我想用边列表绘制杠铃图Barbell(10,10)

0 1
0 2
0 3
0 4
0 5
0 6
0 7
0 8
0 9
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
2 3
2 4
2 5
2 6
2 7
2 8
2 9
3 4
3 5
3 6
3 7
3 8
3 9
4 5
4 6
4 7
4 8
4 9
5 6
5 7
5 8
5 9
6 7
6 8
6 9
7 8
7 9
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
16 17
17 18
18 19
19 20
20 21
20 22
20 23
20 24
20 25
20 26
20 27
20 28
20 29
21 22
21 23
21 24
21 25
21 26
21 27
21 28
21 29
22 23
22 24
22 25
22 26
22 27
22 28
22 29
23 24
23 25
23 26
23 27
23 28
23 29
24 25
24 26
24 27
24 28
24 29
25 26
25 27
25 28
25 29
26 27
26 28
26 29
27 28
27 29
28 29

我使用以下代码来可视化此图:

import numpy as np 
import networkx as nx
barbell = nx.read_edgelist('graph/barbell.edgelist')

classes = [0,] * len(gnx.nodes)
nonzero = m2 + 2
first = range(1,(nonzero + 1) // 2 + 1)
second = reversed(range(1,nonzero - len(first) + 1))
classes[m1 - 1 : (m1 + m2) + 1] = list(first) + list(second)

nx.draw(gnx,node_color=classes,cmap="jet")

然后,我可以得到如下图像:

enter image description here

然而,这篇论文struc2vec,使用相同的边缘,并绘制了一个很好的布局如下:

enter image description here

那么是否可以使用networkx来改进像上面这样的杠铃图的布局?还是需要我使用其他工具?

解决方法

这应该会让你开始。

import networkx as nx
import matplotlib.pyplot as plt

n_clique,n_path = 10,10
clique1 = nx.complete_graph(n_clique)
clique1_pos = nx.circular_layout(clique1)
clique2 = nx.complete_graph(n_clique)
clique2_mapping = {node: node + n_clique for node in clique2}
nx.relabel_nodes(clique2,clique2_mapping,copy=False) # avoids repeated nodes
x_diff,y_diff = 8,-1
clique2_pos = {node: clique1_pos[node-n_clique] + (x_diff,y_diff) for node in clique2}
path = nx.path_graph(n_path)
path_mapping = {node: node + 2 * n_clique for node in path}
nx.relabel_nodes(path,path_mapping,copy=False) # avoids repeated nodes
path_nodes = list(path.nodes)
path_half1_nodes = path_nodes[:n_path//2]
path_half2_nodes = path_nodes[n_path//2:]
path_dist = 0.9
clique2_entry = n_clique + n_clique // 2
path_half1_pos = {node: clique1_pos[0] + (path_dist + i * path_dist,0) for i,node in enumerate(path_half1_nodes)}
path_half2_pos = {node: clique2_pos[clique2_entry] - (path_dist + i * path_dist,node in enumerate(path_half2_nodes[::-1])}
path_pos = {**path_half1_pos,**path_half2_pos}
barbell = nx.Graph()
barbell.add_edges_from(clique1.edges)
barbell.add_edges_from(clique2.edges)
barbell.add_edges_from(path.edges)
barbell.add_edges_from([(path_half1_nodes[0],0),(path_half2_nodes[-1],clique2_entry)])
clique_pos = {**clique1_pos,**clique2_pos}
barbell_pos = {**clique_pos,**path_pos}
plt.figure(figsize=(20,6))
nx.draw(barbell,pos=barbell_pos,with_labels=True)

Output