web-dev-qa-db-fra.com

enregistrer le tableau numpy en mode ajout

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.

21
user3820991

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
18
rth

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.

4
Mohit Pandey

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

1
Evgeny Remizov

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

1
PaxRomana99

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]
0
Sakhri Houssem