Python 我想将节点和距离矩阵转换为一个表,其中包含节点1、节点2的列以及它们之间的距离
我正在使用csv文件,该文件包含每个节点的标题和每个节点的对应行,每个数据字段对应两个节点之间的差异,如下所示: 空白 4. 38 71 90 94 ... 8545 4. 0 1280 1762 1406 1589 ... 1017 38 1280 0 681 202 385 ... 1433 71 1762 681 0 503 0 ... 0 90 1406 202 503 0 0 ... 1559 94 1589 385 0 0 0 ... 1742 .. .. ... ... ... ... 0 ... 8545 1017 1433 0 1559 1742 ... 0Python 我想将节点和距离矩阵转换为一个表,其中包含节点1、节点2的列以及它们之间的距离,python,pandas,numpy,networkx,Python,Pandas,Numpy,Networkx,我正在使用csv文件,该文件包含每个节点的标题和每个节点的对应行,每个数据字段对应两个节点之间的差异,如下所示: 空白 4. 38 71 90 94 ... 8545 4. 0 1280 1762 1406 1589 ... 1017 38 1280 0 681 202 385 ... 1433 71 1762 681 0 503 0 ... 0 90 1406 202 503 0 0 ... 1559 94 1589 385 0 0 0 ... 1742 .. .. ... ... ... .
我想用的是熊猫 A只是有一些或多或少相似的随机数据 现在,我们使用
df = pd.DataFrame(A, columns = [ "node_" + str(i) for i in range(A.shape[0])])
您可以df.stack()
您可以将其设置为带有pd的数据帧。数据帧(df_堆叠)使用此处可获得更好的性能,如带有列表理解的pd.concat:
df2 = df.stack().rename_axis(['Node1','Node2']).reset_index(name='Distance')
print (df2.head(15))
Node1 Node2 Distance
0 4 4 0
1 4 38 1280
2 4 71 1762
3 4 90 1406
4 4 94 1589
5 4 8545 1017
6 38 4 1280
7 38 38 0
8 38 71 681
9 38 90 202
10 38 94 385
11 38 8545 1433
12 71 4 1762
13 71 38 681
14 71 71 0
另一个想法是使用numpy:
c = np.tile(df.columns, len(df))
i = np.repeat(df.index, len(df.columns))
v = np.ravel(df)
df2 = pd.DataFrame({'Node1':i, 'Node2':c, 'Distance':v})
性能:
#6k rows
df = pd.concat([df] * 1000, ignore_index=True)
# print(df)
In [37]: %timeit df2 = pd.DataFrame({'Node1':np.repeat(df.index, len(df.columns)), 'Node2':np.tile(df.columns, len(df)), 'Distance':np.ravel(df)})
1.77 ms ± 42.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [38]: %timeit df.stack().rename_axis(['Node1','Node2']).reset_index(name='Distance')
4.39 ms ± 475 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [39]: %timeit pd.concat([pd.DataFrame([[i, j, df.at[i, j]]], columns=['Node1', 'Node2', 'Distance']) for i in df.index for j in df.columns], ignore_index=True)
31.6 s ± 1.22 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
对于大多数图形操作,如果使用图形库,您将发现巨大的优势。在这种情况下,您可以轻松地从数据帧创建一个图形,并将这些距离添加为 然后,对于所需的输出,在这种情况下,您只需要检索图形边缘的权重,这可以使用以下工具轻松完成: 或者,如果希望将结果作为数据帧:
(pd.DataFrame(weights.keys(), columns=['node1', 'node2'])
.assign(Distance=weights.values()))
node1 node2 Distance
0 94 4 1589
1 94 38 385
2 4 38 1280
3 4 71 1762
4 4 90 1406
5 38 71 681
6 38 90 202
7 71 90 503
如果您有兴趣对数据执行图形操作,因为您当前的任务是将邻接矩阵转换为边列表,我还建议您查看包。如果你想走那条路,然后我会使用方法添加一个答案。是的,我希望稍后使用这些数据来解决具有多个起始节点的TSP版本,因此我非常欣赏这种回答方式。Yatu已经写了一个答案,包括创建networkx图-对于TSP,我还发现了另一个可能相关的问题:numpy对元素的顺序/完整性?如果是这样,很高兴知道。美好的overview@user3184950-是,如果需要,也可以使用参数顺序。不同的顺序OP要求的是距离(与原始df中的值相同),而不是相关系数索引。这只是一些数据,具有相似的对角线。
c = np.tile(df.columns, len(df))
i = np.repeat(df.index, len(df.columns))
v = np.ravel(df)
df2 = pd.DataFrame({'Node1':i, 'Node2':c, 'Distance':v})
#6k rows
df = pd.concat([df] * 1000, ignore_index=True)
# print(df)
In [37]: %timeit df2 = pd.DataFrame({'Node1':np.repeat(df.index, len(df.columns)), 'Node2':np.tile(df.columns, len(df)), 'Distance':np.ravel(df)})
1.77 ms ± 42.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [38]: %timeit df.stack().rename_axis(['Node1','Node2']).reset_index(name='Distance')
4.39 ms ± 475 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [39]: %timeit pd.concat([pd.DataFrame([[i, j, df.at[i, j]]], columns=['Node1', 'Node2', 'Distance']) for i in df.index for j in df.columns], ignore_index=True)
31.6 s ± 1.22 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
import networkx as nx
G = nx.from_pandas_adjacency(df)
weights = nx.get_edge_attributes(G, 'weight')
print(weights)
{(94, 4): 1589,
(94, 38): 385,
(4, 38): 1280,
(4, 71): 1762,
(4, 90): 1406,
(38, 71): 681,
(38, 90): 202,
(71, 90): 503}
(pd.DataFrame(weights.keys(), columns=['node1', 'node2'])
.assign(Distance=weights.values()))
node1 node2 Distance
0 94 4 1589
1 94 38 385
2 4 38 1280
3 4 71 1762
4 4 90 1406
5 38 71 681
6 38 90 202
7 71 90 503