Python 以附加模式保存numpy数组

Python 以附加模式保存numpy数组,python,numpy,save,Python,Numpy,Save,是否可以保存一个numpy数组,并将其附加到一个已经存在的npy文件中——类似于np.save(filename,arr,mode='a') 我有几个函数必须遍历大型数组的行。由于内存限制,我无法立即创建数组。为了避免一次又一次地创建行,我希望创建每一行一次并将其保存到文件中,并将其附加到文件中的前一行。稍后,我可以在mmap_模式下加载npy文件,在需要时访问切片。内置的。npy文件格式非常适合处理小型数据集,无需依赖除numpy之外的外部模块 但是,当您开始拥有大量数据时,最好使用设计用于处

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


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

内置的
。npy
文件格式非常适合处理小型数据集,无需依赖除
numpy
之外的外部模块

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

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

步骤1:创建可扩展存储

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

步骤3:读回数据的子集


要使用numpy.save将数据附加到现有文件,我们应使用:

f_handle = file(filename, 'a')
numpy.save(f_handle, arr)
f_handle.close()
我已经检查过它是否在Python2.7和Numpy1.10.4中工作


我已经改编了中的代码,其中谈到了savetxt方法。

.npy
文件包含具有数组形状和数据类型的标题。如果您知道生成的数组是什么样子的,您可以自己编写头,然后将数据分块写入。例如,以下是连接2d矩阵的代码:

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] :(不能开箱即用)
[2] :

[3] :

您可以尝试读取文件,然后添加新数据

import numpy as np
import os.path

x = np.arange(10) #[0 1 2 3 4 5 6 7 8 9]

y = np.load("save.npy") if os.path.isfile("save.npy") else [] #get data if exist
np.save("save.npy",np.append(y,x)) #save the new
2次手术后:

print(np.load("save.npy")) #[0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]

这是对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)))
从pathlib导入路径
将numpy作为np导入
导入操作系统
p=路径('temp.npy')
p.open('ab')作为f:
np.save(f,np.zero(2))
np.save(f,np.ones(2))
p.open('rb')作为f:
fsz=os.fstat(f.fileno()).st_size
输出=np.负载(f)
而f.tell()
out=数组([[0,0.],[1,1.]]


以下是基于PaxRomana99的答案。 它创建了一个可用于保存和加载数组的类。 理想情况下,每次添加新数组时,也会更改npy文件的标头,以修改形状的描述(有关标头的描述,请参阅)

将numpy导入为np
进口泡菜
从pathlib导入路径
导入操作系统
类npyAppendableFile():
def u uu init uuuu(self,fname,newfile=True):
'''
创建可追加文件类型的新实例
如果newfile为True,则即使文件已存在,也要重新创建该文件
'''
self.fname=路径(fname)
如果是新文件:
以open(self.fname,“wb”)作为fh:
fh.close()
def写入(自身、数据):
'''
将新数组追加到文件
请注意,这不会更改标题
'''
以open(self.fname,“ab”)作为fh:
np.保存(fh,数据)
def负载(自身,轴=2):
'''
加载整个文件,返回连续加载的所有数组
相互叠加保存
axis定义数组应如何连接
'''
以open(self.fname,“rb”)作为fh:
fsz=os.fstat(fh.fileno()).st_size
输出=np.负载(fh)
而fh.tell()
我制作了一个库来创建Numpy
.npy
文件,这些文件通过在零轴上追加而大于机器的主内存。然后可以使用
mmap_mode=“r”
读取该文件

安装:

pip安装npy追加数组

例如:

从npy\u append\u数组导入NpyAppendArray
将numpy作为np导入
arr1=np.数组([[1,2],[3,4]]
arr2=np.数组([[1,2],[3,4],[5,6]]
filename='out.npy'
#可选,.append将自动创建不存在的文件
np.save(文件名,arr1)
npaa=NpyAppendArray(文件名)
npaa.append(arr2)
npaa.append(arr2)
npaa.append(arr2)
data=np.load(文件名,mmap_mode=“r”)
打印(数据)

感谢您为我指点PyTables。对于我来说,使用Array类的方法稍微简单一点就足够了。我很好奇为什么
np.save
没有附加模式。如果合理的话,我想应该已经实施了。这是s吗
import numpy as np
import os.path

x = np.arange(10) #[0 1 2 3 4 5 6 7 8 9]

y = np.load("save.npy") if os.path.isfile("save.npy") else [] #get data if exist
np.save("save.npy",np.append(y,x)) #save the new
print(np.load("save.npy")) #[0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]
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)))
import numpy as np
import pickle

from pathlib import Path
import os


class npyAppendableFile():
    def __init__(self, fname, newfile=True):
        '''
        Creates a new instance of the appendable filetype
        If newfile is True, recreate the file even if already exists
        '''
        self.fname=Path(fname)
        if newfile:
            with open(self.fname, "wb") as fh:
                fh.close()
        
    def write(self, data):
        '''
        append a new array to the file
        note that this will not change the header
        '''
        with open(self.fname, "ab") as fh:
            np.save(fh, data)
            
    def load(self, axis=2):
        '''
        Load the whole file, returning all the arrays that were consecutively
        saved on top of each other
        axis defines how the arrays should be concatenated
        '''
        
        with open(self.fname, "rb") as fh:
            fsz = os.fstat(fh.fileno()).st_size
            out = np.load(fh)
            while fh.tell() < fsz:
                out = np.concatenate((out, np.load(fh)), axis=axis)
            
        return out
    
    
    def update_content(self):
        '''
        '''
        content = self.load()
        with open(self.fname, "wb") as fh:
            np.save(fh, content)

    @property
    def _dtype(self):
        return self.load().dtype

    @property
    def _actual_shape(self):
        return self.load().shape
    
    @property
    def header(self):
        '''
        Reads the header of the npy file
        '''
        with open(self.fname, "rb") as fh:
            version = np.lib.format.read_magic(fh)
            shape, fortran, dtype = np.lib.format._read_array_header(fh, version)
        
        return version, {'descr': dtype,
                         'fortran_order' : fortran,
                         'shape' : shape}
                
        
      
arr_a = np.random.rand(5,40,10)
arr_b = np.random.rand(5,40,7)    
arr_c = np.random.rand(5,40,3)    

f = npyAppendableFile("testfile.npy", True)        

f.write(arr_a)
f.write(arr_b)
f.write(arr_c)

out = f.load()

print (f.header)
print (f._actual_shape)

# after update we can load with regular np.load()
f.update_content()


new_content = np.load('testfile.npy')
print (new_content.shape)