我有一个csv格式(~14GB)的大型有向图,边缘用以下格式表示为整数:
node1,node2
3213741,23521361
3213741,6532710
3213741,12340611
3213741,6457392
3213741,9682135
6567133,12956771
6567133,23860123
node1
是边缘开始的地方,node2
是边缘结束的地方。边缘按node1
分组(可以按node2
分组)。
我需要为所有节点生成两步邻居。这是以下格式:
node1,node2,node3
3213741,6532710,5347128
我的想法是复制边缘并按node2对它们进行排序,因此有两个表t1.node1,t1.node2
和t2.node1,t2.node2
,然后在t1.node1 == t2.node1
和{{}} {{}}时以某种方式连接这两个表{1}}。但这看起来太慢了。是否有更好的算法或任何算法可以利用数据按t1.node1 != t2.node2
分组的事实?我更喜欢Numpy。谢谢。
答案 0 :(得分:2)
根据你的内存有多大,你可以创建一个邻接矩阵作为scipy.sparse.coo_matrix
(即每当两个节点连接并且其他地方为零时有一个矩阵),将其转换为另一种类型的稀疏矩阵然后走广场。该矩阵具有准确存在二阶连接的条目。条目的值甚至可以告诉您长度为2的节点之间存在多少条路径。
答案 1 :(得分:2)
我写了一些代码,实现了obachtos提出的稀疏矩阵方法,并使用dask在一个节点上并行运行:
import numpy as np
import pandas as pd
import dask
import time
from scipy.sparse import coo_matrix
np.random.seed(1)
# Fabricate some data
elem = int(1e7)
rng = int(1e5)
gr = np.random.randint(0, rng, elem * 2, np.uint32)
gr = gr.reshape((elem, 2))
gr = gr[np.argwhere(gr[:, 0] != gr[:, 1])]
gr = gr.reshape(-1, 2)
grdf = pd.DataFrame(data=gr)
gr = grdf.drop_duplicates().values
def coord2adjacency(coords, shp, order, chunksize):
grsp = coo_matrix((np.ones(gr.shape[0]), (gr[:, 0], gr[:, 1])),
shape=(shp, shp))
grcsr = grsp.tocsr()
adj = grcsr**order
return adj
adjspdel = dask.delayed(coord2adjacency,
pure=True, nout=1, traverse=False)(gr, shp=rng,
order=2,
chunksize=5000)
print('Computing an adjacency matrix of order {ordr} from {n} coordinates.'\
.format(ordr=2, n=gr.shape[0]))
t0 = time.time()
adjsp = adjspdel.compute()
print('Execution time: {tm} minutes.'.format(tm=(time.time() - t0) / 60))
在我的4核/ 8 GB PC上,执行时间为4.1分钟。 OP的问题仍然是几个数量级。 dask distributed包应允许与此类似的代码在足够大的任务集群上运行。