【发布时间】:2016-12-05 21:32:04
【问题描述】:
我有一个来自文本文件中图形的 1.2GB 边列表。我的 ubuntu PC 有 8GB 的 RAM。输入中的每一行看起来像
287111206 357850135
我想将其转换为稀疏邻接矩阵并将其输出到文件中。
我的数据的一些统计数据:
Number of edges: around 62500000
Number of vertices: around 31250000
我之前在https://stackoverflow.com/a/38667644/2179021 上问过同样的问题,并得到了很好的答案。问题是我无法让它工作。
我首先尝试将 np.loadtxt 加载到文件中,但它非常慢并且使用了大量内存。因此,我改为使用 pandas.read_csv,它非常快,但这导致了它自己的问题。这是我当前的代码:
import pandas
import numpy as np
from scipy import sparse
data = pandas.read_csv("edges.txt", sep=" ", header= None, dtype=np.uint32)
A = data.as_matrix()
print type(A)
k1,k2,k3=np.unique(A,return_inverse=True,return_index=True)
rows,cols=k3.reshape(A.shape).T
M=sparse.coo_matrix((np.ones(rows.shape,int),(rows,cols)))
print type(M)
问题是 pandas 数据框 data 很大,我实际上是在 A 中复制效率低下。然而,当代码崩溃时,事情变得更糟了
<type 'instancemethod'>
Traceback (most recent call last):
File "make-sparse-matrix.py", line 13, in <module>
rows,cols=k3.reshape(A.shape).T
AttributeError: 'function' object has no attribute 'shape'
raph@raph-desktop:~/python$ python make-sparse-matrix.py
<type 'numpy.ndarray'>
Traceback (most recent call last):
File "make-sparse-matrix.py", line 12, in <module>
k1,k2,k3=np.unique(A,return_inverse=True,return_index=True)
File "/usr/local/lib/python2.7/dist-packages/numpy/lib/arraysetops.py", line 209, in unique
iflag = np.cumsum(flag) - 1
File "/usr/local/lib/python2.7/dist-packages/numpy/core/fromnumeric.py", line 2115, in cumsum
return cumsum(axis, dtype, out)
MemoryError
所以我的问题是:
- 能否避免在内存中同时保存 1.2GB 的 pandas 数据帧和 1.2GB 的 numpy 数组副本?
- 有没有办法让代码在 8GB 的 RAM 中完成?
您可以重现我尝试处理的大小的测试输入:
import random
#Number of edges, vertices
m = 62500000
n = m/2
for i in xrange(m):
fromnode = str(random.randint(0, n-1)).zfill(9)
tonode = str(random.randint(0, n-1)).zfill(9)
print fromnode, tonode
更新
我现在尝试了许多不同的方法,但都失败了。这是一个摘要。
- 将igraph 与
g = Graph.Read_Ncol('edges.txt')一起使用。这会使用大量 RAM,导致我的计算机崩溃。 - 将networkit 与
G= networkit.graphio.readGraph("edges.txt", networkit.Format.EdgeList, separator=" ", continuous=False)一起使用。这会使用大量 RAM,导致我的计算机崩溃。 - 此问题中的上述代码但使用 np.loadtxt("edges.txt") 而不是 pandas。这会使用大量 RAM,导致我的计算机崩溃。
然后我编写了单独的代码,将所有顶点名称重新映射为从 1..|V| 开始的数字。其中|V|是顶点的总数。这应该可以节省导入边列表的代码,而不必建立一个映射顶点名称的表。我试过用这个:
- 使用这个新的重新映射边缘列表文件,我再次使用 igraph 和
g = Graph.Read_Edgelist("edges-contig.txt")。尽管它需要 4GB 的 RAM(这比它应该的理论量要多得多),但它现在可以工作了。但是,没有 igraph 函数可以从图中写出稀疏邻接矩阵。推荐的解决方案是convert the graph to a coo_matrix。不幸的是,这使用了大量的 RAM,导致我的计算机崩溃。 - 使用重新映射的边缘列表文件,我将 networkit 与
G = networkit.readGraph("edges-contig.txt", networkit.Format.EdgeListSpaceOne)一起使用。这也可以使用少于 igraph 所需的 4GB。 networkit 还带有一个编写 Matlab 文件的功能(这是一种 scipy 可以读取的稀疏邻接矩阵形式)。但是networkit.graphio.writeMat(G,"test.mat")使用了大量的 RAM,导致我的计算机崩溃。
最后 sascha 的回答完成了,但需要大约 40 分钟。
【问题讨论】:
-
每一列中的所有数字都是唯一的吗?
-
@khredos 不,他们不是。我生成假数据的示例代码在这方面是不现实的。
-
@eleanora A的形状是什么?嗯......没关系...... A 似乎不是一个数组/矩阵。那很糟!向我们展示 data.head()!你是如何使用 np.loadtxt() 的?
-
关于副本:您可以在 .as_matrix 之后使用
data=None。但在此之前的问题就是这里的问题! -
或许这样可以解决问题:stackoverflow.com/questions/1938894/…
标签: python pandas numpy optimization scipy