Подтвердить что ты не робот

Сохранить массив numpy в режиме добавления

Можно ли сохранить массив numpy, добавив его в уже существующий npy файл - что-то вроде np.save(filename,arr,mode='a')?

У меня есть несколько функций, которые нужно перебирать по строкам большого массива. Я не могу создать массив сразу из-за ограничений памяти. Чтобы избежать создания строк снова и снова, я хотел создать каждую строку один раз и сохранить ее в файл, добавив ее в предыдущую строку в файле. Позже я мог загрузить npy файл в mmap_mode, обращаясь к срезам, когда это необходимо.

4b9b3361

Ответ 1

Встроенный формат файла .npy отлично подходит для работы с небольшими наборами данных, не полагаясь на внешние модули, кроме numpy.

Однако, когда вы начинаете получать большие объемы данных, предпочтение следует отдавать использованию формата файла, такого как HDF5, предназначенного для обработки таких наборов данных [1].

Например, ниже представлено решение для сохранения массивов numpy в HDF5 с PyTables,

Шаг 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()

Шаг 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

Ответ 2

Чтобы добавить данные к уже существующему файлу с помощью numpy.save, мы должны использовать:

f_handle = file(filename, 'a')
numpy.save(f_handle, arr)
f_handle.close()

Я проверил, что он работает в python 2.7 и numpy 1.10.4

Я адаптировал код здесь, в котором говорится о методе savetxt.

Ответ 3

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

Если вам нужно более общее решение (отредактируйте заголовок на месте при добавлении), вам придется прибегать к трюкам 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

Ответ 4

вы можете попробовать что-то вроде чтения файла, а затем добавить новые данные

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]

Ответ 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)))

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