numpy.array()データを適切に保存およびロードする方法は?


103

どうやってnumpy.arrayデータを適切に保存してロードするのか。現在、私はnumpy.savetxt()メソッドを使用しています。たとえば、markers次のような配列を取得したとします。

ここに画像の説明を入力してください

私はそれを使ってそれを保存しようとします:

numpy.savetxt('markers.txt', markers)

他のスクリプトでは、以前に保存したファイルを開こうとします。

markers = np.fromfile("markers.txt")

そして、それは私が得るものです...

ここに画像の説明を入力してください

保存されたデータは、最初は次のようになります。

0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00
0.000000000000000000e+00

しかし、同じ方法を使用してロードしたデータを保存すると、numpy.savetxt()次のようになります。

1.398043286095131769e-76
1.398043286095288860e-76
1.396426376485745879e-76
1.398043286055061908e-76
1.398043286095288860e-76
1.182950697433698368e-76
1.398043275797188953e-76
1.398043286095288860e-76
1.210894289234927752e-99
1.398040649781712473e-76

何が悪いのですか?PS私が実行する他の「バックステージ」操作はありません。保存してロードするだけで、それが実現します。前もって感謝します。


テキストファイルの出力は何ですか?CSVファイルに書き込むだけではどうですか。

4
人間が読めるテキストファイルとして保存およびロードする必要がありますか?およびを使用np.save()してバイナリファイルを保存/ロードすると、処理が速くなります(ファイルはよりコンパクトになります)np.load()
ali_m

アドバイスありがとうございます。それは役に立ちました。しかし、それが何であるのか、そしてデータを* .txt形式で保存し、頭痛なくロードできるようにする方法があるかどうかを説明できますか?たとえば、matlab、java、またはその他のツール/言語で作業したい場合。
bluevoxel 2015

3
配列をMATLABとの間でやり取りするには、scipy.io.savematおよびを使用できますscipy.io.loadmat
ali_m 2015

2
のデフォルトでfromfileは、データをバイナリとして読み取ります。 loadtxtはとの正しいペアリングsavetxtです。関数のドキュメントをご覧ください。
hpaulj

回答:


144

これを実行するために私が見つけた最も信頼できる方法は、で使用することnp.savetxtnp.loadtxtあり、np.fromfileで作成したバイナリファイルには適していませんtofilenp.fromfileそしてnp.tofile、一方の方法が書いて、バイナリファイルを読み込むnp.savetxtテキストファイルを書き込みます。したがって、たとえば:

In [1]: a = np.array([1, 2, 3, 4])
In [2]: np.savetxt('test1.txt', a, fmt='%d')
In [3]: b = np.loadtxt('test1.txt', dtype=int)
In [4]: a == b
Out[4]: array([ True,  True,  True,  True], dtype=bool)

または:

In [5]: a.tofile('test2.dat')
In [6]: c = np.fromfile('test2.dat', dtype=int)
In [7]: c == a
Out[7]: array([ True,  True,  True,  True], dtype=bool)

私は前者の方法を使用しますが、速度が遅く、大きなファイルを作成する場合があります(場合によって)。バイナリ形式はプラットフォームに依存する場合があります(たとえば、ファイル形式はシステムのエンディアンに依存します)。

あるプラットフォームに依存しないで保存して読み取ることができnumpyのアレイの形式は、np.savenp.load

In  [8]: np.save('test3.npy', a)    # .npy extension is added if not given
In  [9]: d = np.load('test3.npy')
In [10]: a == d
Out[10]: array([ True,  True,  True,  True], dtype=bool)

45
.npyファイル(たとえばによって生成されるnp.save()プラットフォームに依存せず、テキストファイルよりもコンパクトで高速に作成できます。
ali_m

2
またnp.savez、出力を圧縮したい場合。
tegan

3
@tegan np.savezはいくつかの配列を非圧縮で保存します- np.savez_compressedそれらを圧縮します- np.save_compressedまだありません。docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.htmlを
Brian Burns

1
ありがとうxnx np.loadtxtでnp.savetxtを使用して同じ問題を(dtype floatで)解決しました
Yogesh

2GBを超えるピクル保存データに問題がありました。xnxのおかげで、a.tofileとnp.fromfileを使用することで問題が解決しました。
Azhar hussain


3

np.fromfile()持っているsep=キーワード引数を:

ファイルがテキストファイルの場合、アイテム間の区切り文字。空の( "")区切り記号は、ファイルをバイナリとして扱う必要があることを意味します。区切り文字のスペース(””)は、ゼロ個以上の空白文字と一致します。スペースのみで構成されるセパレータは、少なくとも1つの空白と一致する必要があります。

のデフォルト値は、スペースで区切られたテキストファイルではなくバイナリファイルとして読み取ろうとするため、sep=""意味のnp.fromfile()ない値が返されます。使用np.fromfile('markers.txt', sep=" ")すると、探している結果が得られます。

ただし、他の人が指摘したnp.loadtxt()ように、テキストファイルをnumpy配列に変換する方法として推奨されます。ファイルを人間が読めるようにする必要がない限り、通常は代わりにバイナリ形式(np.load()/などnp.save())を使用することをお勧めします。


使用に問題はありpickleますか?
チャーリーパーカー

0

短い答えにはnp.saveand を使用する必要がありnp.loadます。これらの利点は、それらがnumpyライブラリの開発者によって作成され、すでに機能していることです(さらに、おそらくすでに適切に最適化されています)。

import numpy as np
from pathlib import Path

path = Path('~/data/tmp/').expanduser()
path.mkdir(parents=True, exist_ok=True)

lb,ub = -1,1
num_samples = 5
x = np.random.uniform(low=lb,high=ub,size=(1,num_samples))
y = x**2 + x + 2

np.save(path/'x', x)
np.save(path/'y', y)

x_loaded = np.load(path/'x.npy')
y_load = np.load(path/'y.npy')

print(x is x_loaded) # False
print(x == x_loaded) # [[ True  True  True  True  True]]

拡張された答え:

人間が読める形式(このNumPy配列をcsvファイルにダンプする)で保存することも、ファイルが非常に大きい場合は他のライブラリで保存することもできるため(最終的にはnumpy配列を保持する最善の方法を参照)詳細なディスカッションのためにディスク上で)。

ただし、(質問で「適切に」という単語を使用しているため、拡張を行います)numpy関数をそのまま使用すると(そしてほとんどのコード!)、ほとんどのユーザーのニーズを満たすと思います。最も重要な理由は、それがすでに機能していることです。他の理由で他のものを使用しようとすると、予期せぬ長いウサギの穴に行き、それが機能しない理由を理解して強制的に機能させる可能性があります。

たとえば、漬物で保存しようとします。私はそれをただ楽しむために試してみましたが、でバイトモードでファイルを開いて読み取らない限り、pickleがファイルを保存しないことを認識するのに少なくとも30分かかりましたwb。グーグル、試してみる、エラーメッセージなどを理解するのに時間がかかりました...細かいことですが、複雑なファイルを予期しない方法で開く必要があるという事実。これを追加するには、これをもう一度読む必要がありました(どちらが混乱を招くのでしょうか)組み込みのオープン関数のモードa、a +、w、w +、r +の違い?

したがって、ニーズに合ったインターフェースがある場合は、(非常に)正当な理由がない限り(たとえば、MATLABとの互換性がある場合や、何らかの理由でファイルを読み取りたい場合や、Pythonでの印刷が本当にニーズに合わない場合)、それを使用してください。疑わしいかもしれません)。さらに、それを最適化する必要がある場合はおそらく、後で説明します(単純なnumpyファイルを開くなど、役に立たないものを何年もデバッグするのではなく)。

したがって、interface / numpyを使用します。それは完璧ではないかもしれません、それはおそらく特に問題があるくらい長い間存在していたライブラリーにとっては問題ないでしょう。

私はすでに多くの方法でnumpyを使用してデータを保存およびロードしましたので、楽しんでください、それが役に立てば幸いです!

import numpy as np
import pickle
from pathlib import Path

path = Path('~/data/tmp/').expanduser()
path.mkdir(parents=True, exist_ok=True)

lb,ub = -1,1
num_samples = 5
x = np.random.uniform(low=lb,high=ub,size=(1,num_samples))
y = x**2 + x + 2

# using save (to npy), savez (to npz)
np.save(path/'x', x)
np.save(path/'y', y)
np.savez(path/'db', x=x, y=y)
with open(path/'db.pkl', 'wb') as db_file:
    pickle.dump(obj={'x':x, 'y':y}, file=db_file)

## using loading npy, npz files
x_loaded = np.load(path/'x.npy')
y_load = np.load(path/'y.npy')
db = np.load(path/'db.npz')
with open(path/'db.pkl', 'rb') as db_file:
    db_pkl = pickle.load(db_file)

print(x is x_loaded)
print(x == x_loaded)
print(x == db['x'])
print(x == db_pkl['x'])
print('done')

私が学んだことについてのいくつかのコメント:

  • np.save予想どおり、これはすでに十分に圧縮されており(https://stackoverflow.com/a/55750128/1601580を参照)、ファイルを開かなくてもそのまま使用できます。掃除。簡単です。効率的。これを使って。
  • np.savezは非圧縮形式を使用します(docsを参照)Save several arrays into a single file in uncompressed .npz format.これを使用する場合(標準のソリューションから離れるよう警告されたため、バグを予想してください!)デフォルトの名前を使用します。したがって、最初のものがすでに機能している場合は、これを使用しないでください(または、他のすべての機能がそれを使用します!)
  • Pickleは、任意のコード実行も可能にします。セキュリティ上の理由でこれを使いたくない人もいるでしょう。
  • 人間が読めるファイルは作るのに費用がかかります。たぶん、それだけの価値はありません。
  • hdf5大きなファイルに呼ばれるものがあります。涼しい!https://stackoverflow.com/a/9619713/1601580

これは完全な答えではありません。しかし、他のリソースについてはこれを確認してください:

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.