如何从大列表创建Numpy数组 - Python
我有一个包含1200行和500,000列的列表的列表。我该如何把它转换成一个numpy数组呢?
我看过关于如何解决“数组太大”这个错误的解决方案,但都没用。
我试着把它们放进一个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.
我还试了hdf5,正如@askewchan建议的那样:
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数组里 =(
5 个回答
还有一个替代方案如下:
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])]
这个方案和你最开始的形式差不多,希望能适应你的代码。不过我无法用你的数据来测试,因为我的内存不够,无法处理这个数组。
你有没有试过指定数据类型?这样做对我有效。
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)
使用 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
在一台有32GB内存和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
如果你执行 print carr.flavor
,它会返回 'numpy'
。你可以像使用NumPy数组一样使用这个 carr
。这些信息是存储在硬盘上的,但访问速度依然很快。
问题看起来是你正在使用的 某个东西(可能是操作系统或者Python)只有32位,这就是导致大小限制的原因。解决办法就是升级到64位的版本。