web-dev-qa-db-fra.com

Ecritures incrémentielles sur hdf5 avec h5py

J'ai une question sur la meilleure façon d'écrire dans des fichiers hdf5 avec python/h5py.

J'ai des données comme:

-----------------------------------------
| timepoint | voltage1 | voltage2 | ...
-----------------------------------------
| 178       | 10       | 12       | ...
-----------------------------------------
| 179       | 12       | 11       | ...
-----------------------------------------
| 185       | 9        | 12       | ...
-----------------------------------------
| 187       | 15       | 12       | ...
                    ...

avec environ 10 ^ 4 colonnes et environ 10 ^ 7 lignes. (Cela représente environ 10 ^ 11 (100 milliards) éléments, soit ~ 100 Go avec 1 octet).

Avec ces données, l'utilisation typique consiste à écrire une fois, à lire plusieurs fois, et le cas de lecture typique serait de récupérer la colonne 1 et une autre colonne (disons 254), de charger les deux colonnes en mémoire et de faire des statistiques fantaisistes.

Je pense qu'une bonne structure hdf5 serait donc que chaque colonne du tableau ci-dessus soit un groupe hdf5, résultant en 10 ^ 4 groupes. De cette façon, nous n'aurons pas besoin de lire toutes les données en mémoire, oui? La structure hdf5 n'est pas encore définie, elle peut donc être n'importe quoi.

Maintenant, la question: je reçois les données ~ 10 ^ 4 lignes à la fois (et pas exactement le même nombre de lignes à chaque fois), et j'ai besoin de les écrire progressivement dans le fichier hdf5. Comment écrire ce fichier?

J'envisage python et h5py, mais pourrait un autre outil s'il est recommandé. Est en train de tronquer la voie à suivre, avec par exemple.

dset = f.create_dataset("voltage284", (100000,), maxshape=(None,), dtype='i8', chunks=(10000,))

puis lorsqu'un autre bloc de 10 ^ 4 lignes arrive, remplacer le jeu de données?

Ou est-il préférable de simplement stocker chaque bloc de 10 ^ 4 lignes comme un ensemble de données distinct? Ou ai-je vraiment besoin de connaître le nombre final de lignes? (Ce sera difficile à obtenir, mais peut-être possible).

Je peux aussi utiliser le hdf5 si ce n'est pas le bon outil pour le travail, même si je pense qu'une fois les écritures maladroites terminées, ce sera merveilleux.

24
user116293

Selon la FAQ , vous pouvez développer l'ensemble de données en utilisant dset.resize. Par exemple,

import os
import h5py
import numpy as np
path = '/tmp/out.h5'
os.remove(path)
with h5py.File(path, "a") as f:
    dset = f.create_dataset('voltage284', (10**5,), maxshape=(None,),
                            dtype='i8', chunks=(10**4,))
    dset[:] = np.random.random(dset.shape)        
    print(dset.shape)
    # (100000,)

    for i in range(3):
        dset.resize(dset.shape[0]+10**4, axis=0)   
        dset[-10**4:] = np.random.random(10**4)
        print(dset.shape)
        # (110000,)
        # (120000,)
        # (130000,)
27
unutbu

Comme l'a souligné @unutbu, dset.resize est une excellente option. Il peut être utile de regarder pandas et son support HDF5 qui peuvent être utiles compte tenu de votre flux de travail. Il semble que HDF5 soit un choix raisonnable compte tenu de vos besoins, mais il est possible que votre problème soit mieux exprimé en utilisant une couche supplémentaire sur le dessus.

Une grande chose à considérer est l'orientation des données. Si vous êtes principalement intéressé par les lectures et que vous récupérez principalement les données par colonne, il semble que vous souhaitiez peut-être transposer les données de sorte que les lectures puissent se produire par ligne car HDF5 stocke dans l'ordre de ligne principale.

7
daniel