Добавочные записи в hdf5 с h5py

У меня есть вопрос о том, как лучше всего писать в hdf5 файлы с помощью python/h5py.

У меня есть такие данные, как:

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

с около 10 ^ 4 столбцами и около 10 ^ 7 строк. (Это около 10 ^ 11 (100 миллиардов) элементов, или ~ 100 ГБ с 1 байтами).

С этими данными типичное использование - это в большинстве случаев однократная запись, многократное чтение, и типичным случаем чтения будет захват столбца 1 и другого столбца (скажем, 254), загрузка обоих столбцов в память и выполнение какой-то интересной статистики.

Я думаю, что хорошая структура hdf5 должна состоять в том, чтобы каждый столбец в таблице выше был группой hdf5, что привело бы к 10 ^ 4 группам. Таким образом, нам не нужно будет читать все данные в память, да? Однако структура hdf5 еще не определена, поэтому она может быть чем угодно.

Теперь вопрос: Я получаю данные ~ 10 ^ 4 строки за раз (и каждый раз не одно и то же число строк), и мне нужно записать их постепенно в файл hdf5. Как мне написать этот файл?

Я рассматриваю python и h5py, но могу порекомендовать другой инструмент. Пробивает путь, например,

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

а затем, когда прибудет еще один блок из 10 ^ 4 строк, заменить набор данных?

Или лучше просто хранить каждый блок из 10 ^ 4 строк в виде отдельного набора данных? Или мне действительно нужно знать окончательное количество строк? (Это будет сложно получить, но, возможно, возможно).

Я могу взять залог за hdf5, если он тоже не подходит для работы, хотя я думаю, что, как только неловкие записи будут сделаны, это будет замечательно.

Ответ 1

В разделе FAQ вы можете расширить набор данных с помощью dset.resize. Например,

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

Ответ 2

Как отметил @unutbu, dset.resize - отличный вариант. Возможно, вам покажется pandas и его поддержка HDF5 полезной, учитывая ваш рабочий процесс. Похоже, что HDF5 - разумный выбор, учитывая ваши потребности, но возможно, что ваша проблема может быть выражена лучше с помощью дополнительного слоя сверху.

Одной из важных вещей является ориентация данных. Если вас в первую очередь интересуют операции чтения, и вы в основном выбираете данные по столбцам, то, похоже, вы захотите транспонировать данные таким образом, чтобы чтения могли происходить по строкам, поскольку HDF5 хранит их в порядке следования строк.