Est-il possible de sauvegarder un tableau numpy en l'ajoutant à un fichier npy existant - quelque chose comme np.save(filename,arr,mode='a')
?
J'ai plusieurs fonctions qui doivent parcourir les lignes d'un grand tableau. Je ne peux pas créer le tableau à la fois à cause des contraintes de mémoire. Pour éviter de créer les lignes encore et encore, je voulais créer chaque ligne une fois et l'enregistrer dans un fichier en l'ajoutant à la ligne précédente du fichier. Plus tard, je pourrais charger le fichier npy dans mmap_mode, en accédant aux tranches si nécessaire.
Le format de fichier .npy
intégré convient parfaitement pour travailler avec de petits ensembles de données, sans recourir à des modules externes autres que numpy
.
Toutefois, lorsque vous commencez à disposer de grandes quantités de données, il est préférable d'utiliser un format de fichier, tel que HDF5, conçu pour gérer de tels ensembles de données, [1]
Par exemple, voici une solution pour enregistrer les tableaux numpy
dans HDF5 avec PyTables ,
Étape 1: Créer un EArray
extensible _ stockage
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()
Étape 2: Ajout de lignes à un jeu de données existant (si nécessaire)
f = tables.open_file(filename, mode='a')
f.root.data.append(x)
Étape 3: relire un sous-ensemble des données
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
Pour ajouter des données à un fichier existant à l'aide de numpy.save, nous devrions utiliser:
f_handle = file(filename, 'a')
numpy.save(f_handle, arr)
f_handle.close()
J'ai vérifié que cela fonctionne en python 2.7 et numpy 1.10.4
J'ai adapté le code de ici , qui parle de la méthode savetxt.
Les fichiers .npy
contiennent un en-tête qui contient la forme et le type du tableau. Si vous savez à quoi ressemble le tableau résultant, vous pouvez écrire vous-même un en-tête, puis des données en morceaux. Par exemple, voici le code pour concaténer des matrices 2D:
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'))
Si vous avez besoin d'une solution plus générale (modifiez l'en-tête lors de l'ajout), vous devrez recourir à des astuces fseek
comme dans [1].
Inspiré par
[1]: https://mail.scipy.org/pipermail/numpy-discussion/2009-August/044570.html (ne fonctionne pas immédiatement)
[2]: https://docs.scipy.org/doc/numpy/neps/npy-format.html
[3]: https://github.com/numpy/numpy/blob/master/numpy/lib/format.py
Ceci est une extension de la réponse de Mohit Pandey montrant un exemple complet de sauvegarde/chargement. Il a été testé avec Python 3.6 et Numpy 1.11.3.
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.]])
vous pouvez essayer quelque chose comme lire le fichier puis ajouter de nouvelles données
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
après 2 opérations:
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]