Zastanawiam się, jak numpy.array
poprawnie zapisywać i ładować dane. Obecnie używam numpy.savetxt()
metody. Na przykład, jeśli mam tablicę markers
, która wygląda tak:
Staram się to uratować za pomocą:
numpy.savetxt('markers.txt', markers)
W innym skrypcie próbuję otworzyć zapisany wcześniej plik:
markers = np.fromfile("markers.txt")
I to właśnie dostaję ...
Zapisane dane wyglądają najpierw tak:
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
Ale kiedy zapisuję właśnie załadowane dane tą samą metodą tj. numpy.savetxt()
To wygląda tak:
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
Co ja robię źle? PS nie ma innej operacji „za kulisami”, którą wykonuję. Tylko zapisuję i ładuję i to właśnie dostaję. Z góry dziękuję.
np.save()
inp.load()
.scipy.io.savemat
iscipy.io.loadmat
.fromfile
są odczytywane jako binarne.loadtxt
to prawidłowe parowanie zsavetxt
. Spójrz na dokumentację funkcji.Odpowiedzi:
Najbardziej niezawodnym sposobem znalazłem to zrobić, aby skorzystać
np.savetxt
znp.loadtxt
a nienp.fromfile
który jest lepiej dostosowany do plików binarnych z pisemnychtofile
.np.fromfile
Inp.tofile
metody zapisu i odczytu plików binarnych, natomiastnp.savetxt
zapisuje plik tekstowy. Na przykład: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)
Lub:
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)
Używam tej pierwszej metody, nawet jeśli jest wolniejsza i tworzy większe pliki (czasami): format binarny może być zależny od platformy (na przykład format pliku zależy od endianness twojego systemu).
Istnieje niezależny od platformy format tablic NumPy, który można zapisywać i odczytywać za pomocą
np.save
inp.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)
źródło
.npy
Pliki (np. generowane przeznp.save()
) są niezależne od platformy i będą bardziej kompaktowe i szybsze w tworzeniu niż pliki tekstowe.np.savez
jeśli chcesz skompresować dane wyjściowe.np.savez
zapisuje kilka nieskompresowanych tablic -np.savez_compressed
skompresuje je -np.save_compressed
jeszcze nie ma . Zobacz docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.htmlnp.save('data.npy', num_arr) # save new_num_arr = np.load('data.npy') # load
źródło
pickle
?x = db["x"]
następniey = db["y"]
?array.shape
i()
wracałem.np.fromfile()
masep=
argument słowa kluczowego:Domyślna wartość
sep=""
oznacza, żenp.fromfile()
próbuje odczytać go jako plik binarny, a nie jako plik tekstowy z wartościami oddzielonymi spacjami, więc zwracane są bezsensowne wartości. Jeśli go użyjesznp.fromfile('markers.txt', sep=" ")
, otrzymasz wynik, którego szukasz.Jednak, jak zauważyli inni,
np.loadtxt()
jest to preferowany sposób konwersji plików tekstowych na tablice numpy i jeśli plik nie musi być czytelny dla człowieka, zwykle lepiej jest użyć zamiast tego formatów binarnych (np.np.load()
/np.save()
).źródło
pickle
?Aby uzyskać krótką odpowiedź, użyj
np.save
inp.load
. Zaletą tego jest to, że są one tworzone przez programistów biblioteki numpy i już działają (plus prawdopodobnie są już ładnie zoptymalizowane) np.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]]
Rozszerzona odpowiedź:
Ostatecznie zależy to od twoich potrzeb ponieważ możesz również zapisać to w formacie czytelnym dla człowieka (zobacz ten Zrzuć tablicę NumPy do pliku csv ) lub nawet z innymi bibliotekamijeśli twoje pliki są bardzo duże (zobacz ten najlepszy sposób na zachowanie tablic numpy na dysku dla rozszerzonej dyskusji).
Jednak (robiąc rozwinięcie, ponieważ w swoim pytaniu użyłeś słowa „prawidłowo”) nadal uważam, że używanie funkcji numpy po wyjęciu z pudełka (i większości kodu!) Najprawdopodobniej zaspokoi większość potrzeb użytkowników. Najważniejszym powodem jest to, że już działa . Próba użycia czegoś innego z jakiegokolwiek innego powodu może doprowadzić cię do nieoczekiwanie DŁUGIEJ króliczej nory, aby dowiedzieć się, dlaczego to nie działa, i zmusić to.
Weźmy na przykład próbę uratowania go marynatą. Próbowałem tego tylko dla zabawy i zajęło mi co najmniej 30 minut, zanim zdałem sobie sprawę, że marynata nie zapisałaby moich rzeczy, chyba że otworzę i przeczytam plik w trybie bajtów za pomocą
wb
. Zajęło trochę czasu, żeby wygooglować, spróbować, zrozumieć komunikat o błędzie itp. Drobny szczegół, ale fakt, że już wymagało to ode mnie otwarcia pliku, skomplikował sprawę w nieoczekiwany sposób. Aby dodać, że wymagało to ponownego przeczytania (co przy okazji jest trochę zagmatwane) Różnica między trybami a, a +, w, w + i r + we wbudowanej funkcji open? .Więc jeśli istnieje interfejs, który spełnia twoje potrzeby, użyj go, chyba że masz ( bardzo ) dobry powód (np. Zgodność z matlabem lub z jakiegoś powodu naprawdę chcesz odczytać plik, a drukowanie w Pythonie naprawdę nie spełnia twoich potrzeb), może budzić wątpliwości). Co więcej, najprawdopodobniej, jeśli chcesz go zoptymalizować, dowiesz się później (zamiast spędzać lata na debugowaniu bezużytecznych rzeczy, takich jak otwieranie prostego pliku numpy).
Więc użyj interfejsu / numpy dostarcza . To może nie być idealne, najprawdopodobniej w porządku, szczególnie w przypadku biblioteki, która istnieje tak długo, jak odrętwienie.
Spędziłem już sporo czasu na zapisywaniu i ładowaniu danych z numpy, więc baw się dobrze, mam nadzieję, że to pomoże!
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')
Kilka komentarzy na temat tego, czego się nauczyłem:
np.save
zgodnie z oczekiwaniami, to już dobrze kompresuje (patrz https://stackoverflow.com/a/55750128/1601580 ), działa po wyjęciu z pudełka bez otwierania pliku. Czysty. Łatwy. Wydajny. Użyj tego.np.savez
używa nieskompresowanego formatu (patrz dokumentacja )Save several arrays into a single file in uncompressed
.npzformat.
Jeśli zdecydujesz się użyć tego (ostrzeżono Cię, aby odejść od standardowego rozwiązania, więc spodziewaj się błędów!), możesz odkryć, że musisz użyć nazw argumentów, aby go zapisać, chyba że chcesz użyj nazw domyślnych. Więc nie używaj tego, jeśli pierwsza już działa (lub jakieś prace używają tego!)hdf5
dużych plików. Fajne! https://stackoverflow.com/a/9619713/1601580Zauważ, że to nie jest wyczerpująca odpowiedź. Ale w przypadku innych zasobów sprawdź to:
np.save
): Zapisz Numpy Array za pomocą Pickleźródło