如何从一个大型列表创建一个Numpy数组- Python

5
我有一个包含1200行和500000列的列表。如何将它转换成numpy数组?
我已经阅读了在绕过“数组太大”Python错误上的解决方案,但它们并没有帮助。
我尝试将它们放入numpy数组中:
import random
import numpy as np
lol = [[random.uniform(0,1) for j in range(500000)] for i in range(1200)]
np.array(lol)

[错误]:

ValueError: array is too big.

然后我尝试了 pandas

import random
import pandas as pd
lol = [[random.uniform(0,1) for j in range(500000)] for i in range(1200)]
pd.lib.to_object_array(lol).astype(float)

[错误]:

ValueError: array is too big.

我也尝试了 @askewchan 建议的hdf5:

import h5py
filearray = h5py.File('project.data','w')
data = filearray.create_dataset('tocluster',(len(data),len(data[0])),dtype='f')
data[...] = data

[错误]:

    data[...] = data
  File "/usr/lib/python2.7/dist-packages/h5py/_hl/dataset.py", line 367, in __setitem__
    val = numpy.asarray(val, order='C')
  File "/usr/local/lib/python2.7/dist-packages/numpy/core/numeric.py", line 460, in asarray
    return array(a, dtype, copy=False, order=order)
  File "/usr/lib/python2.7/dist-packages/h5py/_hl/dataset.py", line 455, in __array__
    arr = numpy.empty(self.shape, dtype=self.dtype if dtype is None else dtype)
ValueError: array is too big.

这篇文章表明我可以将一个巨大的numpy数组存储在磁盘中Python: 如何在PyTables中存储numpy多维数组?。但是,我甚至无法将我的列表嵌套转换为numpy数组=(


列表(列表)当前是如何存储的?它是在磁盘上还是在内存中计算的? - askewchan
无法重现,即使在32位系统上,您也不应该得到“数组太大”的错误,因为数组根本不太大。那么您使用的numpy版本是什么?您能否使用lol = [[0] * 500000] * 1200; a = np.array(lol)进行复现(更加-内存-高效的测试方法)? - seberg
1
算了,如果你正在使用32位的numpy/python(忘记了itemsize因素),那就太大了。你应该升级,因为显然你可以使用大量的内存,这个系统不可能真的是32位的吧? - seberg
如果无法将所有数据放入内存(即创建numpy数组),则需要采用分块方法。使用hdf5,并在块上执行映射-减少操作,而不是读取所有数据。 - Andy Hayden
2
更简洁地说np.zeros((500000, 1200))有效吗? - tacaswell
显示剩余2条评论
5个回答

4
在拥有32GB RAM和64位Python的系统上,您的代码如下:
import random
import numpy as np
lol = [[random.uniform(0,1) for j in range(500000)] for i in range(1200)]
np.array(lol)

对我来说,这种方法很好用,但可能不是最好的选择。这正是PyTables的设计初衷。由于您正在处理同质数据,因此可以使用Array类或更好的CArray类(支持压缩)。操作如下所示:

import numpy as np
import tables as pt

# Create container
h5 = pt.open_file('myarray.h5', 'w')
filters = pt.Filters(complevel=6, complib='blosc')
carr = h5.create_carray('/', 'carray', atom=pt.Float32Atom(), shape=(1200, 500000), filters=filters)

# Fill the array
m, n = carr.shape
for j in xrange(m):
    carr[j,:] = np.random.randn(n) 

h5.close() # "myarray.h5" (~2.2 GB)

# Open file
h5 = pt.open_file('myarray.h5', 'r')
carr = h5.root.carray
# Display some numbers from array
print carr[973:975, :4]
print carr.dtype    

如果您打印carr.flavor,它将返回'numpy'。您可以像使用NumPy数组一样使用此carr。信息存储在磁盘上,但仍然非常快速。

2

使用 h5py / hdf5 技术:

import numpy as np
import h5py

lol = np.empty((1200, 5000)).tolist()

f = h5py.File('big.hdf5', 'w')
bd = f.create_dataset('big_dataset', (len(lol), len(lol[0])), dtype='f')
bd[...] = lol

那么,我相信您可以像访问数组一样访问大数据集bd,但它是存储在磁盘上并从磁盘中访问的,而不是存储在内存中:

In [14]: bd[0, 1:10]
Out[14]:
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.], dtype=float32)

您可以在一个文件中拥有多个“数据集”(多个数组)。

abd = f.create_dataset('another_big_dataset', (len(lol), len(lol[0])), dtype='f')
abd[...] = lol
abd += 10

然后:

In [24]: abd[:3, :10]
Out[24]: 
array([[ 10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.],
       [ 10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.,  10.]], dtype=float32)

In [25]: bd[:3, :10]
Out[25]: 
array([[ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.]], dtype=float32)

我的电脑无法处理你的例子,因此我无法用与你的数组大小相同的数组进行测试,但是我希望它能够工作!

根据你想要对数组进行的操作,你可能会在pytables中有更好的运气,它比h5py做得更多。

另请参阅:
Python Numpy非常大的矩阵
在SQLite和HDF5格式中从/导入到numpy、scipy的导出


太糟糕了,它对于numpy来说仍然太大了。 - alvas
2
我不明白。这不是一个numpy数组。 - askewchan

1

你尝试过指定dtype吗?这对我有效。

import random
import numpy as np
lol = [[random.uniform(0,1) for j in range(500000)] for i in range(1200)]
ar = np.array(lol, dtype=np.float64)

另一个选择是使用blaze。http://blaze.pydata.org/
import random
import blaze
lol = [[random.uniform(0,1) for j in range(500000)] for i in range(1200)]
ar = blaze.array(lol)

你有多少内存? - Michael WS

0
问题似乎是您正在使用只有32位的某些东西(无论是操作系统还是Python),这是大小限制的根源。解决方案是升级到64位。

似乎是这样,http://stackoverflow.com/questions/17756791/python-process-using-only-1-6-gb-ram-ubuntu-32-bit-in-numpy-array - alvas

-2

另一种选择是以下内容:

lol = np.empty((1200,500000))
for i in range(lol.shape[0]):
    lol[i] = [random.uniform(0,1) for j in range(lol.shape[1])]

这个代码与您最初的形式相当接近,我希望它可以适用于您的代码。由于我的内存无法处理该数组,因此无法使用您的数字进行测试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接