2014-09-04 12 views
10

Mam pytanie dotyczące tego, jak najlepiej napisać do plików hdf5 z python/h5py.przyrostowe zapisy do hdf5 z h5py

mam danych: a

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

około 10^4 kolumny, oraz około 10^7 rzędach. (To około 10^11 (100 miliardów) elementów lub ~ 100 GB z 1-bajtowym wzorcem).

Z tymi danymi typowe zastosowanie to zapisanie jednokrotnie, wielokrotne czytanie, a typowym przypadkiem odczytu jest przechwytywanie kolumny 1 i kolejnej kolumny (powiedzmy 254), ładowanie obu kolumn do pamięci i wykonywanie fantazyjnych statystyk .

Myślę, że dobrą strukturą hdf5 byłoby, aby każda kolumna w powyższej tabeli była grupą hdf5, co daje 10^4 grup. W ten sposób nie będziemy musieli czytać wszystkich danych w pamięci, tak? Struktura hdf5 nie jest jeszcze zdefiniowana, więc może być dowolna.

Teraz pytanie: Otrzymuję dane ~ 10^4 wiersze na raz (i nie dokładnie taką samą liczbę wierszy za każdym razem), i trzeba napisać go przyrostowo do pliku hdf5. Jak mogę napisać ten plik?

Rozważam użycie Pythona i H5py, ale w razie potrzeby można użyć innego narzędzia. Czyni to do zrobienia, np.

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

a gdy inny blok 10^4 rzędy przybywa wymienić zestaw danych?

A może lepiej jest przechowywać każdy blok 10^4 wierszy jako osobny zestaw danych? Czy naprawdę muszę znać ostatnią liczbę wierszy? (To będzie trudne, ale możliwe).

Mogę zaokrętować się na hdf5, jeśli nie jest to odpowiednie narzędzie do tego zadania, choć myślę, że po wykonaniu niezręcznych zapisów, będzie cudownie.

Odpowiedz

13

Per the FAQ, można rozszerzyć zestaw danych za pomocą dset.resize. Na przykład,

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

czy dtype = 'i8' coś? Myślę, że "int8" ma 8 bitów, ale i8 wydaje się większy. – user116293

+1

'i8' są dla 8-bajtowych ints. Możesz sprawdzić rozmiar bajtu za pomocą 'np.dtype ('i8'). Itemsize'. Jeśli chcesz 1-bajtowe ints, użyj 'np.int8' (alias' i1''). – unutbu

3

Jak @unutbu wskazał, dset.resize jest doskonałym rozwiązaniem. Może to zadziałać, gdy przyjrzymy się pandas i jego obsłudze HDF5, która może być przydatna, biorąc pod uwagę twój przepływ pracy. Brzmi to tak, jakby HDF5 był rozsądnym wyborem, biorąc pod uwagę twoje potrzeby, ale możliwe jest, że twój problem może być lepiej wyrażony za pomocą dodatkowej warstwy na wierzchu.

Jedną z ważnych rzeczy do rozważenia jest orientacja danych. Jeśli interesujesz się głównie czytaniem, a przede wszystkim pobierasz dane według kolumn, to brzmi to tak, jakbyś chciał przetransponować dane tak, aby odczyty mogły się zdarzyć z wiersza jako magazynów HDF5 w rządowej kolejności.