在append mod中保存numpy数组

2024-04-23 11:48:08 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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


Tags: 文件函数内存numpymodesavenp模式
3条回答

这是Mohit Pandey答案的扩展,显示了一个完整的保存/加载示例。它使用Python3.6和Numpy1.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)))

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

.npy文件包含头,头中包含数组的形状和数据类型。如果知道结果数组的外观,可以自己编写头,然后将数据分块写入。E、 下面是连接二维矩阵的代码:

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

如果您需要一个更通用的解决方案(在追加时在位编辑头),则必须使用像[1]中那样的fseek技巧。

灵感来自
[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

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

但是,当您开始拥有大量数据时,最好使用设计用于处理此类数据集的文件格式(如HDF5)。

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

步骤1:创建可扩展的^{}存储

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

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

f = tables.open_file(filename, mode='a')
f.root.data.append(x)

步骤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

相关问题 更多 >