如何增加networkx.spring_layout的节点间距

55

使用

绘制一个团(clique)图。

import networkx as nx
....
nx.draw(G, layout=nx.spring_layout(G))

该代码产生如下图片:

enter image description here

显然,节点之间的间距(例如边长)需要增加。我在谷歌上搜索了一下,并在这里找到了如下建议:

对于某些布局算法,可能会有一个scale参数可以帮助解决问题,例如:

import networkx as nx
G = nx.path_graph(4)
pos = nx.spring_layout(G)  # default to scale=1
nx.draw(G, pos)
pos = nx.spring_layout(G, scale=2)  # double distance between all nodes
nx.draw(G, pos)
然而,scale 参数似乎没有任何作用。 要获得更好的绘图方法是什么?

1
除了下面提供的答案之外,我还发现增加图形大小会有所帮助。 - ericmjl
3个回答

72

解决这个问题的方法在于 NetworkX 版本 1.8,该版本尚未发布,但可以通过 GitHub 获取。

请按照以下步骤增加节点之间的距离:

pos = nx.spring_layout(G, k=0.15, iterations=20)
# k controls the distance between the nodes and varies between 0 and 1
# iterations is the number of times simulated annealing is run
# default k=0.1 and iterations=50

调整这些参数以查看它如何工作。但尽管如此,并不能保证所有节点都不重叠。


1
根据 https://networkx.org/documentation/stable/reference/generated/networkx.drawing.layout.spring_layout.html,`k=1/n^(1/2)`,因此在0.1处不稳定。 - MERose
这个答案对我的情况没有帮助,虽然我的情况很相似,但是OrangeSherbet的回答确实有效。 - xagg

20

对于你的问题,真正的答案是你原来的图不是一个单一的,完全连接的组件,而是三个独立的图。

发生的事情是这三个部分会飞向无限远处,在重新缩放后每个组件看起来像一个微小的斑点。

spring_layout算法规定了所有节点之间的斥力(反重力)以及只有连接节点之间的引力(“弹簧”)。

因此,如果图不是连通的,则各个子图将因为没有连接它们而受到斥力而飞离。有两种选择:更改力的定律(编辑networkx代码),或将组件分别绘制为一个图。

下面是如何添加一个将所有节点吸引到图表中心的力。将这段代码片段的最后一行添加到layouts.py中的def _fruchterman_reingold中:

# displacement "force"
displacement = np.einsum('ijk,ij->ik',
                         delta,
                         (k * k / distance**2 - A * distance / k))
# ADD THIS LINE - prevent things from flying off into infinity if not connected
displacement = displacement - pos / ( k * np.sqrt(nnodes))

这一行代码使您可以创建像enter image description here这样的图表,而不是enter image description here。但是,“最好”的方法是将组件分别制图。

您可以遍历这些组件,在单独的绘图中绘制它们,使用此处描述的函数。

有关更多讨论,请参见此github问题


16

我使用了Kamada Kawai布局的最优距离参数,并将非连接组件之间的距离设置为图中的最大距离。可能有更好的方法来处理字典,但这相当容易:

df = pd.DataFrame(index=G.nodes(), columns=G.nodes())
for row, data in nx.shortest_path_length(G):
    for col, dist in data.items():
        df.loc[row,col] = dist

df = df.fillna(df.max().max())

layout = nx.kamada_kawai_layout(G, dist=df.to_dict())

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