2014-09-04 25 views
10

Ho una domanda sul modo migliore di scrivere su file hdf5 con python/h5py.scritture incrementali in hdf5 con h5py

Ho dati come:

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

con circa 10^4 colonne, e circa 10^7 righe. (Si tratta di 10^11 (100 miliardi) elementi, o ~ 100 GB con 1 byte int).

Con questi dati, l'uso tipico è praticamente scrivere una volta, leggere molte volte e il tipico caso di lettura sarebbe quello di afferrare la colonna 1 e un'altra colonna (per esempio 254), caricare entrambe le colonne in memoria e fare alcune fantasiose statistiche .

Penso che una buona struttura hdf5 sarebbe quindi quella di avere ciascuna colonna nella tabella sopra un gruppo hdf5, risultante in 10^4 gruppi. In questo modo non avremo bisogno di leggere tutti i dati in memoria, sì? La struttura hdf5 non è ancora definita, quindi può essere qualsiasi cosa.

Ora la domanda: Ricevo i dati ~ 10^4 righe alla volta (e non esattamente lo stesso numero di righe ogni volta) e devo scriverlo in modo incrementale sul file hdf5. Come scrivo quel file?

Sto considerando python e h5py, ma potrebbe essere un altro strumento se consigliato. È chunking la strada da percorrere, con ad es.

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

e quindi quando arriva un altro blocco di 10^4 righe, sostituire il set di dati?

Oppure è meglio archiviare ogni blocco di 10^4 righe come un set di dati separato? O devo davvero conoscere il numero finale di righe? (Sarebbe difficile da ottenere, ma forse possibile).

Posso bail su hdf5 se non è lo strumento giusto anche per il lavoro, anche se penso che una volta che le scomode scritture saranno state fatte, sarà meraviglioso.

risposta

13

Per the FAQ, è possibile espandere il set di dati utilizzando dset.resize. Ad esempio,

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,) 
+0

è dtype = 'i8' una cosa? Penso che 'int8' sia 8 bit, ma i8 sembra essere più grande. – user116293

+1

'i8' sono per 8 byte int. Puoi controllare la dimensione del byte usando 'np.dtype ('i8'). Itemsize'. Se vuoi valori di 1 byte, usa 'np.int8' (aka' 'i1''). – unutbu

3

Come @unutbu indicate, dset.resize è una scelta eccellente. Potrebbe essere utile guardare pandas e il suo supporto HDF5 che potrebbe essere utile dato il tuo flusso di lavoro. Sembra che HDF5 sia una scelta ragionevole date le tue esigenze ma è possibile che il tuo problema possa essere espresso meglio usando un ulteriore strato in cima.

Una cosa importante da considerare è l'orientamento dei dati. Se sei principalmente interessato alle letture e stai principalmente recuperando i dati per colonna, sembra che potresti voler trasporre i dati in modo che le letture possano avvenire per riga mentre HDF5 memorizza in ordine di riga principale.

Problemi correlati