NetworkX最小生成树对相同数据有不同的群集排列?

2024-06-28 20:13:41 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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.imgur.com/pBbcPGc.jpg

但是,当我使用相同的数据重新运行代码并且没有修改时,集群的排列似乎发生了变化,因此看起来就不同了,这里的示例:https://i.imgur.com/4phvFGz.jpg,这里的第二个示例:https://i.imgur.com/f2YepVx.jpg。簇、边和权重似乎没有变化,但它们在图形空间中的排列每次都在变化

是什么导致节点的排列每次都发生变化,而代码或数据没有任何变化?如何重新编写此代码以生成一个网络图,每次为相同的数据使用大致相同的节点和边排列


Tags: 数据代码httpscom图形dataproductsrow
2条回答

为清晰起见,分配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稳定的唯一方法是存储它一次,并在每次重新运行后从文件中检索。您可以将此脚本置于pos之前,以改进的方式计算nx.draw(G, pos=pos, with_labels=True)

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中使用的自定义项

nx.draw方法默认使用spring_layout(link to the doc)。这个布局实现了Fruchterman-Reingold force-directed algorithm,它以随机初始位置开始。这就是您在重复试验中看到的布局效果

如果要“修复”位置,那么应该显式地调用spring_layout函数,并在pos参数中指定初始位置

相关问题 更多 >