web-dev-qa-db-ja.com

追加モードでnumpy配列を保存する

Numpy配列を保存して、既存のnpyファイルに追加することは可能ですか?--- np.save(filename,arr,mode='a')のようなものですか?

大きな配列の行を反復処理する必要のある関数がいくつかあります。メモリの制約のため、一度に配列を作成できません。行を何度も作成することを避けるために、各行を一度作成し、ファイルに保存して、ファイルの前の行に追加したいと思いました。後で、必要に応じてスライスにアクセスして、mmap_modeでnpyファイルをロードできました。

32
user3820991

ビルドイン.npyファイル形式は、numpy以外の外部モジュールに依存することなく、小さなデータセットを扱うのに最適です。

ただし、大量のデータを取得する場合は、そのようなデータセットを処理するために設計されたHDF5などのファイル形式を使用することをお勧めします [1]

たとえば、以下は、HDF5でnumpy配列を PyTables で保存するためのソリューションです。

ステップ1:拡張可能なものを作成 EArray storage

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
22
rth

これは、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.]])

4
PaxRomana99

Numpy.saveを使用して既存のファイルにデータを追加するには、次を使用する必要があります。

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

python 2.7およびnumpy 1.10.4で動作することを確認しました

here のコードを適用しました。これはsavetxtメソッドについて説明しています。

3
Mohit Pandey

.npyファイルには、配列の形状とdtypeを含むヘッダーが含まれています。結果の配列がどのように見えるかがわかっている場合は、ヘッダーを自分で書き、データをチャンクで書き込むことができます。たとえば、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]: 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

2
Evgeny Remizov

あなたはファイルを読んで新しいデータを追加するようなものを試すことができます

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]
0
Sakhri Houssem