Ist es möglich, ein numpy-Array zu speichern, das an eine bereits vorhandene npy-Datei angehängt wird, etwa np.save(filename,arr,mode='a')
?
Ich habe mehrere Funktionen, die über die Zeilen eines großen Arrays iterieren müssen. Ich kann das Array wegen Speicherbeschränkungen nicht sofort erstellen. Um zu vermeiden, dass die Zeilen immer wieder erstellt werden, wollte ich jede Zeile einmal erstellen und in einer Datei speichern, die sie an die vorherige Zeile in der Datei anhängt. Später konnte ich die npy-Datei in mmap_mode laden und bei Bedarf auf die Slices zugreifen.
Das eingebaute .npy
-Dateiformat eignet sich hervorragend für die Arbeit mit kleinen Datensätzen, ohne auf externe Module außer numpy
angewiesen zu sein.
Wenn Sie jedoch mit großen Datenmengen beginnen, ist die Verwendung eines Dateiformats wie HDF5, das für die Verarbeitung solcher Datensätze vorgesehen ist, zu bevorzugen [1] .
Im Folgenden finden Sie eine Lösung zum Speichern von numpy
-Arrays in HDF5 mit PyTables ,
Schritt 1: Erstellen Sie eine erweiterbare EArray
storage
import tables
import numpy as np
filename = 'outarray.h5'
ROW_SIZE = 100
NUM_COLUMNS = 200
f = tables.open_file(filename, mode='w')
atom = tables.Float64Atom()
array_c = f.create_earray(f.root, 'data', atom, (0, ROW_SIZE))
for idx in range(NUM_COLUMNS):
x = np.random.Rand(1, ROW_SIZE)
array_c.append(x)
f.close()
Schritt 2: Anfügen von Zeilen an eine vorhandene Datenmenge (falls erforderlich)
f = tables.open_file(filename, mode='a')
f.root.data.append(x)
Schritt 3: Lesen Sie einen Teil der Daten zurück
f = tables.open_file(filename, mode='r')
print(f.root.data[1:10,2:20]) # e.g. read from disk only this part of the dataset
Für das Anhängen von Daten an eine bereits vorhandene Datei mithilfe von numpy.save sollten wir Folgendes verwenden:
f_handle = file(filename, 'a')
numpy.save(f_handle, arr)
f_handle.close()
Ich habe überprüft, dass es in Python 2.7 und Numpy 1.10.4 funktioniert
Ich habe den Code von here angepasst, der von der savetxt-Methode spricht.
.npy
-Dateien enthalten einen Header, der die Form und den Typ des Arrays enthält. Wenn Sie wissen, wie Ihr resultierendes Array aussieht, können Sie selbst den Header und dann Daten in Abschnitten schreiben. Zum Beispiel ist hier der Code zum Verketten von 2d-Matrizen:
import numpy as np
import numpy.lib.format as fmt
def get_header(fnames):
dtype = None
shape_0 = 0
shape_1 = None
for i, fname in enumerate(fnames):
m = np.load(fname, mmap_mode='r') # mmap so we read only header really fast
if i == 0:
dtype = m.dtype
shape_1 = m.shape[1]
else:
assert m.dtype == dtype
assert m.shape[1] == shape_1
shape_0 += m.shape[0]
return {'descr': fmt.dtype_to_descr(dtype), 'fortran_order': False, 'shape': (shape_0, shape_1)}
def concatenate(res_fname, input_fnames):
header = get_header(input_fnames)
with open(res_fname, 'wb') as f:
fmt.write_array_header_2_0(f, header)
for fname in input_fnames:
m = np.load(fname)
f.write(m.tostring('C'))
Wenn Sie eine allgemeinere Lösung benötigen (Kopfzeile beim Anhängen bearbeiten), müssen Sie auf fseek
-Tricks wie in [1] zurückgreifen.
Inspiriert von
[1]: https://mail.scipy.org/pipermail/numpy-discussion/2009-August/044570.html (funktioniert nicht sofort)
[2]: https://docs.scipy.org/doc/numpy/neps/npy-format.html
[3]: https://github.com/numpy/numpy/blob/master/numpy/lib/format.py
Dies ist eine Erweiterung der Antwort von Mohit Pandey, die ein Beispiel zum vollständigen Speichern/Laden zeigt. Es wurde mit Python 3.6 und Numpy 1.11.3 getestet.
from pathlib import Path
import numpy as np
import os
p = Path('temp.npy')
with p.open('ab') as f:
np.save(f, np.zeros(2))
np.save(f, np.ones(2))
with p.open('rb') as f:
fsz = os.fstat(f.fileno()).st_size
out = np.load(f)
while f.tell() < fsz:
out = np.vstack((out, np.load(f)))
out = Array ([[0., 0.], [1., 1.]])
sie können etwas versuchen, beispielsweise die Datei lesen und neue Daten hinzufügen
import numpy as np
import os.path
x = np.arange(10) #[0 1 2 3 4 5 6 7 8 9]
y = np.load("save.npy") if os.path.isfile("save.npy") else [] #get data if exist
np.save("save.npy",np.append(y,x)) #save the new
nach 2 Operationen:
print(np.load("save.npy")) #[0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9]