NetworkX最小生成树在相同数据下具有不同的簇排列



我有一个大型数据集,它将产品与相关度度量进行比较,如下所示:

product1      product2  relatedness
0101          0102      0.047619
0101          0103      0.023810
0101          0104      0.095238
0101          0105      0.214286
0101          0106      0.047619
...           ...       ...

我使用以下代码将数据输入NetworkX绘图工具并生成MST图:

import networkx as nx
import matplotlib.pyplot as plt
products = (data['product1'])
products = list(dict.fromkeys(products))
products = sorted(products)
G = nx.Graph()
G.add_nodes_from(products)
print(G.number_of_nodes())
print(G.nodes())
row = 0
for c in data['product1']:
p = data['product2'][row]
w = data['relatedness'][row]
if w > 0:
G.add_edge(c,p, weight=w, with_labels=True)
row = row + 1
nx.draw(nx.minimum_spanning_tree(G), with_labels=True)
plt.show()

生成的图表如下所示:https://i.stack.imgur.com/LBrnD.jpg

然而,当我重新运行代码时,使用相同的数据并且没有修改,集群的排列似乎发生了变化,因此看起来有所不同,例如:https://i.stack.imgur.com/jR62Q.jpg,此处的第二个示例:https://i.stack.imgur.com/PLHyo.jpg.簇、边和权重似乎没有变化,但它们在图空间上的排列每次都在变化。

是什么导致节点的排列每次都会发生变化,而不对代码或数据进行任何更改?如何重写此代码以生成每次对相同数据具有大致相同节点和边排列的网络图?

nx.draw方法默认使用spring_layout(指向文档的链接(。此布局实现Fruchterman-Reingold力定向算法,该算法从随机初始位置开始。这就是你在重复试验中看到的布局效果。

如果你想";"修复";位置,则应显式调用spring_layout函数并指定pos参数中的初始位置。

为了清楚起见,分配G = nx.minimum_spanning_tree(G)。然后

nx.draw(G, with_labels=True)

相当于

pos = nx.spring_layout(G)
nx.draw(G, pos=pos, with_labels=True)

由于您不希望每次运行脚本时都随机计算pos,所以保持pos稳定的唯一方法是将其存储一次,并在每次重新运行后从文件中检索。您可以在nx.draw(G, pos=pos, with_labels=True):之前使用此脚本以改进的方式计算pos

import os, json
def store(pos):
#form of dictionary to be stored dictionary retrieved
return {k: v.tolist() for k, v in pos.items()}
def retrieve(pos):
#form of dictionary to be retrieved
return {float(k): v for k, v in pos.items()}
if 'nodes.txt' in os.listdir():
json_file = open('pos.txt').read()
pos = retrieve(json.loads(json_file)) #retrieving dictionary from file
print('retrieve', pos)
else:
with open('pos.txt', 'w') as outfile:
pos = nx.spring_layout(new_G) #calculates pos
print('store', pos)
json.dump(store(pos), outfile, indent=4) #records pos dictionary into file

这是一个丑陋的解决方案,因为它无条件地依赖于pos字典中使用的数据类型。它对我有效,但你可以定义你在storeretrieve中使用的自定义

最新更新