note.nkmk.me

NumPy配列ndarrayをバイナリファイル(npy, npz)で保存

Date: 2019-01-16 / tags: Python, NumPy

NumPyでは配列ndarrayをNumPy独自のバイナリファイル(npy, npz)で保存することが可能。データ型dtypeや形状shapeなどの情報を保持したまま書き込み・読み込み(出力・入力)ができる。

ここでは以下の内容について説明する。

  • バイナリで保存するメリットとデメリット
  • バイナリ(npy, npz)を読み込み: np.load()
  • 一つのndarraynpyで保存: np.save()
  • 複数のndarraynpzで保存: np.savez()
  • 複数のndarrayを圧縮してnpzで保存: np.saves_compressed()

バイナリファイルではなくCSV(カンマ区切り)やTSV(タブ区切り)などのテキストファイルで読み書きしたい場合は以下の記事を参照。

スポンサーリンク

バイナリファイルで保存するメリットとデメリット

メリット

NumPy配列ndarrayをNumPy独自のバイナリファイル(npy, npz)で保存する場合、データ型dtypeや形状shapeなどの情報がそのまま保存される。

例えば3次元以上の多次元配列はCSVファイルなどではそのまま保存できないので形状を変換するなどの何らかの処理が必要だが、バイナリの場合は特に考慮しなくてもよい。

また、テキストファイルで保存する場合は小数点以下の桁数の設定によって値が丸まってしまったりするが、バイナリの場合はデータがそのまま保存される。

デメリット

バイナリファイル(npy, npz)のフォーマットは公開されているが、基本的にはNumPyでのみ使用が可能。

CSVファイルのように他のアプリケーションで開いて中身を確認したり編集したりできない。

npy, npzを読み込み: np.load()

バイナリファイル(npy, npz)の読み込みにはnp.load()を使う。

基本的には引数にファイルのパスを指定するだけだが、npy(一つの配列を格納)とnpz(複数の配列を格納)で扱いが異なる。

それぞれの場合の処理方法は以下のnp.save(), np.savez(), np.savez_compressed()と合わせて説明する。

一つのndarrayをnpyで保存: np.save()

一つの配列ndarrayをバイナリファイルとして保存するにはnp.save()を使う。

以下のndarrayを例とする。

import numpy as np

a = np.arange(5)
print(a)
# [0 1 2 3 4]

第一引数にパス文字列、第二引数に保存したいndarrayを指定する。

np.save('data/temp/np_save', a)

第一引数に指定したパス文字列に拡張子.npyが付与されたファイル名で保存される。

読み込みはnp.load()ndarrayがそのまま返される。

print(type(np.load('data/temp/np_save.npy')))
# <class 'numpy.ndarray'>

print(np.load('data/temp/np_save.npy'))
# [0 1 2 3 4]

データ型を変換したndarrayを保存すると、特に設定しなくてもそのまま入出力できていることが確認できる。

np.save('data/temp/np_save', a.astype('float32'))

b = np.load('data/temp/np_save.npy')

print(b)
# [0. 1. 2. 3. 4.]

print(b.dtype)
# float32

複数のndarrayをnpzで保存: np.savez()

複数の配列ndarrayをまとめて一つのバイナリファイルに保存するにはnp.savez()を使う。

以下の2つのndarrayを例とする。

import numpy as np

a1 = np.arange(5)
print(a1)
# [0 1 2 3 4]

a2 = np.arange(5, 10)
print(a2)
# [5 6 7 8 9]

第一引数にパス文字列、以降に保存したいndarrayをカンマ区切りで指定する。例はndarrayが2つだけだが、可変長引数になっているので、3つ以上の場合もカンマ区切りで指定していけばOK。

np.savez('data/temp/np_savez', a1, a2)

第一引数に指定したパス文字列に拡張子.npzが付与されたファイル名で保存される。

読み込みはnpyと同じくnp.load()だが、返されるのはNpzFileオブジェクト。

print(type(np.load('data/temp/np_savez.npz')))
# <class 'numpy.lib.npyio.NpzFile'>

格納されたndarrayを取得するには、各ndarrayの名前を[]で指定する必要がある。各ndarrayの名前はfiles属性で確認できる。

npz = np.load('data/temp/np_savez.npz')

print(npz.files)
# ['arr_0', 'arr_1']

print(npz['arr_0'])
# [0 1 2 3 4]

print(npz['arr_1'])
# [5 6 7 8 9]

デフォルトでは上の例のように保存時に引数に指定した順番にarr_0, arr_1...という名前が自動的に付けられる。

np.savez()ndarrayを指定するときにキーワード引数の形にすると、任意の名前を付けることが可能。多数のndarrayをまとめて保存する場合は分かりやすい名前を付けておいた方が便利。

np.savez('data/temp/np_savez_kw', x=a1, y=a2)

npz_kw = np.load('data/temp/np_savez_kw.npz')

print(npz_kw.files)
# ['x', 'y']

print(npz_kw['x'])
# [0 1 2 3 4]

print(npz_kw['y'])
# [5 6 7 8 9]

あまり使うことはないかもしれないが、以下のように一部のndarrayのみキーワード引数で名前を付けることもできる。

np.savez('data/temp/np_savez_kw2', a1, y=a2)

npz_kw2 = np.load('data/temp/np_savez_kw2.npz')

print(npz_kw2.files)
# ['y', 'arr_0']

print(npz_kw2['arr_0'])
# [0 1 2 3 4]

print(npz_kw2['y'])
# [5 6 7 8 9]

複数のndarrayを圧縮してnpzで保存: np.saves_compressed()

np.saves_compressed()np.savez()と同じく複数の配列ndarrayをまとめて一つのバイナリファイルに保存する。

唯一の違いはnp.saves_compressed()は圧縮して保存するということ。出力されるファイルのサイズがnp.savez()よりも小さくなる。

拡張子はnp.savez()と同じ.npzで、np.load()での扱いも同じ。

np.savez_compressed('data/temp/np_savez_comp', a1, a2)

print(type(np.load('data/temp/np_savez_comp.npz')))
# <class 'numpy.lib.npyio.NpzFile'>

npz_comp = np.load('data/temp/np_savez_comp.npz')

print(npz_comp.files)
# ['arr_0', 'arr_1']

print(npz_comp['arr_0'])
# [0 1 2 3 4]

print(npz_comp['arr_1'])
# [5 6 7 8 9]

キーワード引数も使える。

np.savez_compressed('data/temp/np_savez_comp_kw', x=a1, y=a2)

npz_comp_kw = np.load('data/temp/np_savez_comp_kw.npz')

print(npz_comp_kw.files)
# ['x', 'y']

print(npz_comp_kw['x'])
# [0 1 2 3 4]

print(npz_comp_kw['y'])
# [5 6 7 8 9]
スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事