Wie speichere und lade ich numpy.array () Daten richtig?

103

Ich frage mich, wie man numpy.arrayDaten richtig speichert und lädt . Derzeit verwende ich die numpy.savetxt()Methode. Wenn ich zum Beispiel ein Array habe markers, das so aussieht:

Geben Sie hier die Bildbeschreibung ein

Ich versuche es zu speichern mit:

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

In einem anderen Skript versuche ich, zuvor gespeicherte Dateien zu öffnen:

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

Und das bekomme ich ...

Geben Sie hier die Bildbeschreibung ein

Gespeicherte Daten sehen zunächst so aus:

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

Aber wenn ich gerade geladene Daten mit der gleichen Methode speichere, dh. numpy.savetxt()es sieht aus wie das:

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

Was mache ich falsch? PS: Es gibt keine andere "Backstage" -Operation, die ich durchführe. Nur speichern und laden, und das bekomme ich. Vielen Dank im Voraus.

Bluevoxel
quelle
Was ist die Ausgabe der Textdatei? Warum nicht einfach in eine CSV-Datei schreiben?
4
Müssen Sie als lesbare Textdateien speichern und laden? Es ist schneller (und die Dateien sind kompakter), wenn Sie Binärdateien mit np.save()und speichern / laden np.load().
Ali_m
Danke für deinen Rat. Es half. Können Sie jedoch erklären, warum es so ist, wie es ist, und ob es eine Möglichkeit gibt, Daten im * .txt-Format zu speichern und ohne Kopfschmerzen zu laden? Zum Beispiel, wenn man mit Matlab, Java oder anderen Tools / Sprachen arbeiten möchte.
Bluevoxel
3
Um Arrays an / von MATLAB zu übergeben, können Sie scipy.io.savematund verwenden scipy.io.loadmat.
Ali_m
2
Standardmäßig werden fromfiledie Daten als binär gelesen. loadtxtist die richtige Paarung mit savetxt. Schauen Sie sich die Funktionsdokumentation an.
hpaulj

Antworten:

144

Der zuverlässigste Weg, den ich gefunden habe, ist die Verwendung np.savetxtmit np.loadtxtund nicht np.fromfiledie, die besser für Binärdateien geeignet ist, mit denen geschrieben wurde tofile. Die Methoden np.fromfileund np.tofileschreiben und lesen Binärdateiennp.savetxt eine Textdatei geschrieben wird. Also zum Beispiel:

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)

Oder:

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)

Ich verwende die erstere Methode, auch wenn sie langsamer ist und (manchmal) größere Dateien erstellt: Das Binärformat kann plattformabhängig sein (z. B. hängt das Dateiformat von der Endianität Ihres Systems ab).

Es ist ein plattformunabhängiges Format für NumPy Arrays, die gespeichert und gelesen werden kann mit np.saveund 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
quelle
45
.npyDateien (z. B. generiert von np.save()) sind plattformunabhängig und kompakter und schneller zu erstellen als Textdateien.
Ali_m
2
auch np.savezwenn Sie die Ausgabe komprimieren möchten.
Tegan
2
@tegan np.savezspeichert mehrere Arrays unkomprimiert - np.savez_compressedkomprimiert sie - es gibt noch keine np.save_compressed. Siehe docs.scipy.org/doc/numpy-1.15.1/reference/routines.io.html
Brian Burns
1
Danke xnx Ich hatte das gleiche Problem (mit dtype float) mit np.savetxt mit np.loadtxt gelöst
Yogesh
Ich hatte ein Problem mit dem Speichern von Daten mit mehr als 2 GB. Dank xnx wurde das Problem mit a.tofile und np.fromfile gelöst.
Azhar Hussain
47
np.save('data.npy', num_arr) # save
new_num_arr = np.load('data.npy') # load
Sherzod
quelle
Gibt es ein Problem mit der Verwendung pickle?
Charlie Parker
können beispielsweise so , dass wir die Daten mit laden , wie x = db["x"]gefolgt von y = db["y"]?
Charlie Parker
3

np.fromfile()hat ein sep=Schlüsselwortargument:

Trennzeichen zwischen Elementen, wenn die Datei eine Textdatei ist. Ein leeres Trennzeichen ("") bedeutet, dass die Datei als binär behandelt werden soll. Leerzeichen (””) im Trennzeichen stimmen mit null oder mehr Leerzeichen überein. Ein Trennzeichen, das nur aus Leerzeichen besteht, muss mit mindestens einem Leerzeichen übereinstimmen.

Der Standardwert von sep=""bedeutet, dass np.fromfile()versucht wird, ihn als Binärdatei und nicht als durch Leerzeichen getrennte Textdatei zu lesen, sodass Sie unsinnige Werte zurückerhalten. Wenn Sie verwenden, erhalten np.fromfile('markers.txt', sep=" ")Sie das gewünschte Ergebnis.

Wie andere bereits np.loadtxt()betont haben, ist dies jedoch die bevorzugte Methode zum Konvertieren von Textdateien in numpy-Arrays. Wenn die Datei nicht für Menschen lesbar sein muss, ist es normalerweise besser, stattdessen Binärformate zu verwenden (z . B. np.load()/ np.save()).

ali_m
quelle
Gibt es ein Problem mit der Verwendung pickle?
Charlie Parker
0

Für eine kurze Antwort sollten Sie np.saveund verwenden np.load. Die Vorteile davon sind, dass sie von Entwicklern der Numpy-Bibliothek erstellt wurden und bereits funktionieren (und wahrscheinlich bereits gut optimiert sind), z

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

Erweiterte Antwort:

Letztendlich hängt es wirklich von Ihren Anforderungen ab, da Sie es auch in einem für Menschen lesbaren Format speichern können (siehe Dump eines NumPy-Arrays in einer CSV-Datei ) oder sogar mit anderen Bibliotheken, wenn Ihre Dateien extrem groß sind (siehe diesen besten Weg, um Numpy-Arrays zu erhalten) auf der Festplatte für eine erweiterte Diskussion).

Wenn Sie jedoch eine Erweiterung vornehmen, da Sie das Wort "richtig" in Ihrer Frage verwenden), denke ich immer noch, dass die sofort einsatzbereite Numpy-Funktion (und der meiste Code!) Wahrscheinlich die meisten Benutzeranforderungen erfüllt. Der wichtigste Grund ist, dass es bereits funktioniert . Der Versuch, aus einem anderen Grund etwas anderes zu verwenden, führt Sie möglicherweise in ein unerwartet langes Kaninchenloch, um herauszufinden, warum es nicht funktioniert, und um es zu erzwingen.

Nehmen wir zum Beispiel den Versuch, es mit Gurke zu speichern. Ich habe das nur zum Spaß versucht und es dauerte mindestens 30 Minuten, bis mir klar wurde, dass pickle meine Sachen nicht speichern würde, wenn ich die Datei nicht im Byte-Modus mit öffnen und lesen würde wb. Es hat einige Zeit gedauert, um zu googeln, etwas auszuprobieren, die Fehlermeldung zu verstehen usw. Kleine Details, aber die Tatsache, dass ich bereits eine Datei öffnen musste, komplizierte Dinge auf unerwartete Weise. Um hinzuzufügen, dass ich dies erneut lesen musste (was übrigens verwirrend ist) Unterschied zwischen den Modi a, a +, w, w + und r + in der eingebauten offenen Funktion?.

Wenn es also eine Schnittstelle gibt, die Ihren Anforderungen entspricht, verwenden Sie diese, es sei denn, Sie haben eine ( sehr ) guten Grund (z. B. Kompatibilität mit Matlab oder aus irgendeinem Grund möchten Sie die Datei wirklich lesen und in Python drucken, was Ihren Anforderungen nicht wirklich entspricht könnte fraglich sein). Darüber hinaus werden Sie es höchstwahrscheinlich später herausfinden, wenn Sie es optimieren müssen (anstatt ewig damit zu verbringen, nutzlose Dinge wie das Öffnen einer einfachen Numpy-Datei zu debuggen).

Verwenden Sie also die Schnittstelle / numpy zur Verfügung stellen . Es ist vielleicht nicht perfekt, es ist höchstwahrscheinlich in Ordnung, besonders für eine Bibliothek, die es schon so lange gibt.

Ich habe das Speichern und Laden von Daten mit numpy bereits auf eine Menge verbracht, also viel Spaß damit, hoffe es hilft!

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

Einige Kommentare zu dem, was ich gelernt habe:

  • np.saveWie erwartet wird es bereits gut komprimiert (siehe https://stackoverflow.com/a/55750128/1601580 ) und funktioniert sofort, ohne dass Dateien geöffnet werden müssen. Reinigen. Einfach. Effizient. Benutze es.
  • np.savezverwendet ein unkomprimiertes Format (siehe Dokumente ) Save several arrays into a single file in uncompressed .npz format.Wenn Sie sich für dieses Format entscheiden (Sie wurden gewarnt, von der Standardlösung abzuweichen , erwarten Sie also Fehler!), stellen Sie möglicherweise fest, dass Sie zum Speichern Argumentnamen verwenden müssen, es sei denn, Sie möchten Verwenden Sie die Standardnamen. Verwenden Sie dies also nicht, wenn das erste bereits funktioniert (oder wenn es funktioniert)!
  • Pickle ermöglicht auch die Ausführung von beliebigem Code. Einige Benutzer möchten dies möglicherweise aus Sicherheitsgründen nicht verwenden.
  • Von Menschen lesbare Dateien sind teuer in der Herstellung usw. Wahrscheinlich nicht wert.
  • Es gibt so etwas wie hdf5große Dateien. Cool! https://stackoverflow.com/a/9619713/1601580

Beachten Sie, dass dies keine vollständige Antwort ist. Für andere Ressourcen überprüfen Sie dies:

Charlie Parker
quelle