在追加模式下保存numpy数组

use*_*991 34 python numpy save

是否可以保存一个numpy数组,将其附加到已经存在的npy文件中np.save(filename,arr,mode='a')

我有几个函数必须遍历大数组的行.由于内存限制,我无法立即创建数组.为了避免一遍又一遍地创建行,我想创建每一行一次并将其保存到文件中,并将其附加到文件中的上一行.稍后我可以在mmap_mode中加载npy文件,在需要时访问切片.

rth*_*rth 24

内置.npy文件格式非常适合处理小型数据集,而不依赖于其他外部模块numpy.

但是,当您开始拥有大量数据时,首选使用旨在处理此类数据集的文件格式(如HDF5)[1].

例如,下面是numpy使用PyTables在HDF5中保存数组的解决方案,

第1步:创建可扩展EArray存储

import tables
import numpy as np

filename = 'outarray.h5'
ROW_SIZE = 100
NUM_COLUMNS = 200

f = tables.open_file(filename, mode='w')
atom = tables.Float64Atom()

array_c = f.create_earray(f.root, 'data', atom, (0, ROW_SIZE))

for idx in range(NUM_COLUMNS):
    x = np.random.rand(1, ROW_SIZE)
    array_c.append(x)
f.close()
Run Code Online (Sandbox Code Playgroud)

第2步:将行附加到现有数据集(如果需要)

f = tables.open_file(filename, mode='a')
f.root.data.append(x)
Run Code Online (Sandbox Code Playgroud)

第3步:回读数据的子集

f = tables.open_file(filename, mode='r')
print(f.root.data[1:10,2:20]) # e.g. read from disk only this part of the dataset
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你把我指向PyTables.使用Array类的一个更简单的方法足以达到我的目的.我很好奇为什么没有'np.save`的追加模式.如果它是明智的,我想它会被实施. (4认同)
  • 这仍然是2018年最好的方法吗? (4认同)
  • HDF5 是否优于 npy 文件格式是一个有争议的论点。越来越多的论文表明,HDF5 实际上是一种非常麻烦的文件格式,例如 exdir 正在转向将数据保存在 numpy 文件中。 (3认同)
  • 关于 2022 年当前最佳实践有什么建议吗? (3认同)
  • 是的,这个答案有点过时了。例如,现在 zarr 也可能成为一种可能性。请随意编辑答案。 (2认同)

小智 9

我创建了一个库,.npy通过在零轴上附加来创建大于机器主内存的Numpy文件。然后可以使用mmap_mode="r".

https://pypi.org/project/npy-append-array

安装:

pip install npy-append-array

例子:

from npy_append_array import NpyAppendArray
import numpy as np

arr1 = np.array([[1,2],[3,4]])
arr2 = np.array([[1,2],[3,4],[5,6]])

filename='out.npy'

# optional, .append will create file automatically if not exists
np.save(filename, arr1)

npaa = NpyAppendArray(filename)
npaa.append(arr2)
npaa.append(arr2)
npaa.append(arr2)

data = np.load(filename, mmap_mode="r")

print(data)
Run Code Online (Sandbox Code Playgroud)


小智 7

.npy文件包含标题,其中包含数组的形状和数据类型。如果您知道生成的数组是什么样的,您可以自己编写标题,然后分块编写数据。例如,这是连接二维矩阵的代码:

import numpy as np
import numpy.lib.format as fmt

def get_header(fnames):
    dtype = None
    shape_0 = 0
    shape_1 = None
    for i, fname in enumerate(fnames):
        m = np.load(fname, mmap_mode='r') # mmap so we read only header really fast
        if i == 0:
            dtype = m.dtype
            shape_1 = m.shape[1]
        else:
            assert m.dtype == dtype
            assert m.shape[1] == shape_1
        shape_0 += m.shape[0]
    return {'descr': fmt.dtype_to_descr(dtype), 'fortran_order': False, 'shape': (shape_0, shape_1)}

def concatenate(res_fname, input_fnames):
    header = get_header(input_fnames)
    with open(res_fname, 'wb') as f:
        fmt.write_array_header_2_0(f, header)
        for fname in input_fnames:
            m = np.load(fname)
            f.write(m.tostring('C'))
Run Code Online (Sandbox Code Playgroud)

如果您需要更通用的解决方案(在附加时就地编辑标题),您将不得不求助于fseek[1] 中的技巧。

启发
:[1] https://mail.scipy.org/pipermail/numpy-discussion/2009-August/044570.html(不盒子的锻炼)
[2]:HTTPS://docs.scipy .org/doc/numpy/neps/npy-format.html
[3]:https : //github.com/numpy/numpy/blob/master/numpy/lib/format.py


Pax*_*a99 5

这是Mohit Pandey回答的扩展,显示了完整的保存/加载示例。已使用Python 3.6和Numpy 1.11.3进行了测试。

from pathlib import Path
import numpy as np
import os

p = Path('temp.npy')
with p.open('ab') as f:
    np.save(f, np.zeros(2))
    np.save(f, np.ones(2))

with p.open('rb') as f:
    fsz = os.fstat(f.fileno()).st_size
    out = np.load(f)
    while f.tell() < fsz:
        out = np.vstack((out, np.load(f)))
Run Code Online (Sandbox Code Playgroud)

out = array([[0.,0.],[1.,1.]])