はじめに
numpy配列を直列化する方法はいろいろあります。numpyから使える方法に限っても4つあります*1。
numpy.savetxt — NumPy v1.15 Manual
numpy.save — NumPy v1.15 Manual
numpy.savez — NumPy v1.15 Manual
numpy.savez_compressed — NumPy v1.15 Manual
出力されるファイルの容量はどれが少ないのでしょうか? なんとなく予想できる気もしますが、検討してみました。
それぞれの簡単な説明
- numpy.savetxt
テキスト形式で保存する。1次元ないし2次元配列しか出力できない
- numpy.save
いわゆる普通の直列化。.npyという拡張子を使うらしい
- numpy.savez
複数の配列を同時に直列化できる。.npzという拡張子を使う。読み込むときは辞書
- numpy.savez_compressed
savezを圧縮して出力するだけ
numpy.savetxtで出力したものはnumpy.loadtxtで読み込む必要があります。それ以外はnumpy.loadで行けるようです。
容量比較
次のようなコードを書きました。
import numpy as np A = np.arange(10**6).astype(np.float64).reshape(10**3, 10**3) np.savetxt("savetxt.txt", A) np.save("save.npy", A) np.savez("savez.npz", A) np.savez_compressed("savez_compressed.npz", A)
出力されたファイルの容量は、
関数 | 容量[MB] |
---|---|
savetxt.txt | 25.0 |
save.npy | 8.0 |
savez.npz | 8.0 |
savez_compressed.npz | 1.3 |
のように、numpy.savez_compressedを使うのが最良でした。
まあ、やる前からわかっていましたが。
考察とまとめ
特にこだわりがなければnumpy.savez_compressedが良さげです。圧縮に時間はかかるはずですが、20倍弱違うとストレージI/Oの時間が短縮できるので相殺できる気がします(未検証)。
難点は.npz形式への親しみのなさでしょうか。save_compressedがあれば良かった気もしますが(特に単一の配列をシリアライズしたい場合など)、同じようなものを複数作る必要はないという思想なのでしょう。しょせんloadするとただの辞書が返るだけなので、そんなに難しく考える必要もなく、numpy.savez_compressed使えば良いですね。
*1:というか、もう少しいろいろある気もする。詳細は Input and output — NumPy v1.15 Manual を参照