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

5 投票
5 回答
6158 浏览
提问于 2025-04-17 22:45

我有一个包含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 个回答

-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])]

这个方案和你最开始的形式差不多,希望能适应你的代码。不过我无法用你的数据来测试,因为我的内存不够,无法处理这个数组。

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)
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

4

在一台有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。这些信息是存储在硬盘上的,但访问速度依然很快。

0

问题看起来是你正在使用的 某个东西(可能是操作系统或者Python)只有32位,这就是导致大小限制的原因。解决办法就是升级到64位的版本。

撰写回答