Bagaimana cara menyimpan dan memuat data numpy.array () dengan benar?

107

Saya bertanya-tanya, bagaimana cara menyimpan dan memuat numpy.arraydata dengan benar. Saat ini saya menggunakan numpy.savetxt()metode tersebut. Misalnya, jika saya mendapatkan array markers, yang terlihat seperti ini:

masukkan deskripsi gambar di sini

Saya mencoba menyimpannya dengan menggunakan:

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

Di skrip lain saya mencoba membuka file yang disimpan sebelumnya:

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

Dan itulah yang saya dapatkan ...

masukkan deskripsi gambar di sini

Data yang disimpan pertama kali terlihat seperti ini:

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

Tapi ketika saya menyimpan data yang dimuat dengan menggunakan metode yang sama, yaitu. numpy.savetxt()ini terlihat seperti ini:

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

Apa yang saya lakukan salah? PS tidak ada operasi "belakang panggung" lain yang saya lakukan. Hanya menyimpan dan memuat, dan itulah yang saya dapatkan. Terima kasih sebelumnya.

bluevoxel.dll
sumber
Apa keluaran dari file teks? Mengapa tidak menulis ke file CSV saja?
5
Apakah Anda perlu menyimpan dan memuat sebagai file teks yang dapat dibaca manusia? Ini akan lebih cepat (dan file akan lebih kompak) jika Anda menyimpan / memuat file biner menggunakan np.save()dan np.load().
ali_m
Terima kasih atas saran Anda. Itu membantu. Namun, dapatkah Anda menjelaskan mengapa demikian, dan apakah ada cara untuk mengizinkan penyimpanan data dalam format * .txt dan memuatnya tanpa pusing? Misalnya ketika ingin bekerja dengan matlab, java, atau tools / bahasa lain.
bluevoxel
3
Untuk melewatkan array ke / dari MATLAB Anda dapat menggunakan scipy.io.savematdan scipy.io.loadmat.
ali_m
2
Defaultnya fromfileadalah membaca data sebagai biner. loadtxtadalah pasangan yang benar dengan savetxt. Lihat dokumentasi fungsi.
hpaulj

Jawaban:

150

Cara yang paling dapat diandalkan saya telah menemukan untuk melakukan ini adalah dengan menggunakan np.savetxtdengan np.loadtxtdan tidak np.fromfileyang lebih cocok untuk file biner yang ditulis dengan tofile. Metode np.fromfiledan np.tofilemenulis dan membaca file biner sambil np.savetxtmenulis file teks. Jadi, misalnya:

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)

Atau:

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)

Saya menggunakan metode sebelumnya meskipun lebih lambat dan membuat file lebih besar (terkadang): format biner dapat bergantung pada platform (misalnya, format file bergantung pada endianness sistem Anda).

Ada format platform independen untuk array NumPy, yang dapat disimpan dan dibaca dengan np.savedan np.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)
xnx
sumber
48
.npyfile (misalnya dihasilkan oleh np.save()) tidak bergantung pada platform, dan akan lebih ringkas dan lebih cepat untuk dibuat daripada file teks.
ali_m
2
juga np.savezjika Anda ingin output dikompresi.
tegan
3
@tegan np.savezmenyimpan beberapa array yang tidak dikompresi - np.savez_compressedakan memampatkannya - np.save_compressedbelum ada . Lihat docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.html
Brian Burns
1
Terima kasih xnx Saya mengalami masalah yang sama (dengan dtype float) menggunakan np.savetxt dengan np.loadtxt menyelesaikannya
Yogesh
Saya memiliki masalah dengan data penyimpanan acar yang lebih besar dari 2GB. Berkat xnx, masalah diselesaikan dengan menggunakan a.tofile dan np.fromfile.
Azr
49
np.save('data.npy', num_arr) # save
new_num_arr = np.load('data.npy') # load
Sherzod
sumber
1
apakah ada masalah dengan penggunaan pickle?
Charlie Parker
Misalnya, agar kita dapat memuat data dengan sebagai x = db["x"]diikuti y = db["y"]?
Charlie Parker
Ketika saya mencoba ini, array saya kembali kosong. Urgh.
Keith
@Keith, apakah Anda baru saja mencoba mencetak sebelum menyimpan array numpy Anda?
Sherzod
@ Sherzod Saya baru saja menggunakan array.shapedan ()kembali.
Keith
3

np.fromfile()memiliki sep=argumen kata kunci:

Pemisah antar item jika file adalah file teks. Pemisah kosong ("") berarti file harus diperlakukan sebagai biner. Spasi (””) di pemisah cocok dengan nol atau lebih karakter spasi. Pemisah yang hanya terdiri dari spasi harus cocok dengan setidaknya satu spasi.

Nilai default dari sep=""sarana yang np.fromfile()mencoba membacanya sebagai file biner daripada file teks yang dipisahkan spasi, sehingga Anda mendapatkan nilai yang tidak masuk akal kembali. Jika Anda menggunakan np.fromfile('markers.txt', sep=" ")Anda akan mendapatkan hasil yang Anda cari.

Namun, seperti yang ditunjukkan orang lain, np.loadtxt()adalah cara yang lebih disukai untuk mengonversi file teks menjadi array numpy, dan kecuali file tersebut harus dapat dibaca manusia, biasanya lebih baik menggunakan format biner sebagai gantinya (misalnya np.load()/ np.save()).

ali_m
sumber
apakah ada masalah dengan penggunaan pickle?
Charlie Parker
1

Untuk jawaban singkat Anda harus menggunakan np.savedan np.load. Keuntungan dari ini adalah bahwa mereka dibuat oleh pengembang perpustakaan numpy dan mereka sudah berfungsi (ditambah kemungkinan sudah dioptimalkan dengan baik) misalnya

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]]

Jawaban yang diperluas:

Pada akhirnya itu benar-benar tergantung pada kebutuhan Anda karena Anda juga dapat menyimpannya dalam format yang dapat dibaca manusia (lihat Dump a NumPy array ke dalam file csv ) atau bahkan dengan pustaka lain jika file Anda sangat besar (lihat cara terbaik ini untuk mempertahankan array numpy pada disk untuk diskusi yang lebih luas).

Namun, (membuat perluasan karena Anda menggunakan kata "dengan benar" dalam pertanyaan Anda) Saya masih berpikir menggunakan fungsi numpy di luar kotak (dan sebagian besar kode!) Kemungkinan besar memenuhi sebagian besar kebutuhan pengguna. Alasan terpenting adalah itu sudah berfungsi . Mencoba menggunakan sesuatu yang lain untuk alasan lain mungkin membawa Anda pada lubang kelinci PANJANG yang tidak terduga untuk mencari tahu mengapa itu tidak berhasil dan memaksanya bekerja.

Ambil contoh mencoba menyimpannya dengan acar. Saya mencobanya hanya untuk bersenang-senang dan butuh setidaknya 30 menit untuk menyadari bahwa acar tidak akan menyimpan barang-barang saya kecuali saya membuka & membaca file dalam mode byte dengan wb. Butuh waktu untuk google, mencoba sesuatu, memahami pesan kesalahan dll .. Detail kecil tetapi fakta bahwa itu sudah mengharuskan saya untuk membuka file hal-hal rumit dengan cara yang tidak terduga. Untuk menambahkan bahwa saya harus membaca ulang ini (btw yang agak membingungkan) Perbedaan antara mode a, a +, w, w +, dan r + dalam fungsi terbuka built-in? .

Jadi jika ada antarmuka yang memenuhi kebutuhan Anda, gunakan kecuali Anda memiliki alasan ( sangat ) bagus (misalnya kompatibilitas dengan matlab atau karena alasan tertentu Anda sangat ingin membaca file dan mencetak dengan python benar-benar tidak memenuhi kebutuhan Anda, yang mana mungkin dipertanyakan). Selain itu, kemungkinan besar jika Anda perlu mengoptimalkannya, Anda akan mengetahuinya nanti (daripada menghabiskan waktu lama untuk men-debug hal-hal yang tidak berguna seperti membuka file numpy sederhana).

Jadi gunakan antarmuka / numpy sediakan . Mungkin tidak sempurna, kemungkinan besar baik-baik saja, terutama untuk perpustakaan yang sudah ada selama numpy.

Saya sudah menghabiskan waktu menyimpan dan memuat data dengan numpy dalam banyak cara jadi bersenang-senanglah dengannya, semoga membantu!

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

Beberapa komentar tentang apa yang saya pelajari:

  • np.saveseperti yang diharapkan, ini sudah memampatkannya dengan baik (lihat https://stackoverflow.com/a/55750128/1601580 ), berfungsi di luar kotak tanpa membuka file apa pun. Bersih. Mudah. Efisien. Gunakan.
  • np.savezmenggunakan format tidak terkompresi (lihat docs ) Save several arrays into a single file in uncompressed .npz format.Jika Anda memutuskan untuk menggunakan ini (Anda diperingatkan untuk keluar dari solusi standar jadi harapkan bug!) Anda mungkin menemukan bahwa Anda perlu menggunakan nama argumen untuk menyimpannya, kecuali Anda ingin gunakan nama default. Jadi jangan gunakan ini jika yang pertama sudah berfungsi (atau karya apa pun menggunakan itu!)
  • Pickle juga memungkinkan eksekusi kode arbitrer. Beberapa orang mungkin tidak ingin menggunakan ini untuk alasan keamanan.
  • file yang dapat dibaca manusia mahal untuk dibuat, dll. Mungkin tidak sepadan.
  • ada sesuatu yang disebut hdf5file besar. Keren! https://stackoverflow.com/a/9619713/1601580

Perhatikan bahwa ini bukanlah jawaban yang lengkap. Tetapi untuk sumber daya lain periksa ini:

Charlie Parker
sumber