numpy:有效地读取大数组

时间:2010-12-06 11:36:08

标签: python performance numpy scipy large-files

我有一个二进制文件,其中包含32位浮点数的密集n*m矩阵。将它读入Fortran排序的numpy数组的最有效方法是什么?

该文件的大小为数千兆字节。我可以控制格式,但它必须是紧凑的(即长度大约4*n*m个字节)并且必须易于从非Python代码生成。

编辑:该方法必须直接生成Fortran排序矩阵(由于数据的大小,我无法创建C有序矩阵然后转换它进入一个单独的Fortran命令副本。)

2 个答案:

答案 0 :(得分:12)

NumPy提供fromfile()来读取二进制数据。

a = numpy.fromfile("filename", dtype=numpy.float32)

将创建一个包含数据的一维数组。要将其作为二维Fortran排序的n x m矩阵进行访问,您可以对其进行整形:

a = a.reshape((n, m), order="FORTRAN")

[编辑:在这种情况下,reshape()实际上复制了数据(请参阅注释)。要在没有cpoying的情况下执行此操作,请使用

a = a.reshape((m, n)).T

感谢Joe Kingtion指出这一点。]

但说实话,如果你的矩阵有几千兆字节,我会选择像h5pyPyTables这样的HDF5工具。这两个工具都有FAQ条目,将工具与另一个工具进行比较。我通常更喜欢h5py,虽然PyTables似乎更常用(两个项目的范围略有不同)。

HDF5文件可以使用数据分析中使用的大多数编程语言编写。链接的维基百科文章中的接口列表不完整,例如还有一个R interface。但实际上我不知道你想用哪种语言写数据......

答案 1 :(得分:1)

基本上Numpy将数组存储为平面向量。多维度只是由Numpy迭代器使用的不同视图和步幅创建的错觉。

有关Numpy内部如何运作的详尽但易于理解的说明,请参阅优秀的chapter 19 on The Beatiful Code book

至少Numpy array()reshape()有一个C('C'),Fortran('F')或保留顺序('A')的参数。 另请参阅问题How to force numpy array order to fortran style?

使用默认C索引(row-major order)的示例:

>>> a = np.arange(12).reshape(3,4) # <- C order by default
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a[1]
array([4, 5, 6, 7])

>>> a.strides
(32, 8)

使用Fortran订单(column-major order)进行索引:

>>> a = np.arange(12).reshape(3,4, order='F')
>>> a
array([[ 0,  3,  6,  9],
       [ 1,  4,  7, 10],
       [ 2,  5,  8, 11]])
>>> a[1]
array([ 1,  4,  7, 10])

>>> a.strides
(8, 24)

另一个视图

此外,您始终可以使用数组的参数T获取其他类型的视图:

>>> a = np.arange(12).reshape(3,4, order='C')
>>> a.T
array([[ 0,  4,  8],
       [ 1,  5,  9],
       [ 2,  6, 10],
       [ 3,  7, 11]])

>>> a = np.arange(12).reshape(3,4, order='F')
>>> a.T
array([[ 0,  1,  2],
       [ 3,  4,  5],
       [ 6,  7,  8],
       [ 9, 10, 11]])

您也可以手动设置步幅:

>>> a = np.arange(12).reshape(3,4, order='C')
>>> a
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
>>> a.strides
(32, 8)
>>> a.strides = (8, 24)
>>> a
array([[ 0,  3,  6,  9],
       [ 1,  4,  7, 10],
       [ 2,  5,  8, 11]])