Как я могу объединить несколько файлов .h5? - PullRequest
0 голосов
/ 01 октября 2019

Все, что доступно онлайн, слишком сложно. Моя база данных велика, чтобы я экспортировал ее по частям. Теперь у меня есть три файла .h5, и я хотел бы объединить их в один файл .h5 для дальнейшей работы. Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 03 октября 2019

В этих примерах показано, как использовать h5py для копирования наборов данных между 2 файлами HDF5. Смотрите мой другой ответ для PyTables примеров. Я создал несколько простых файлов HDF5 для имитации данных типа CSV (все плавающие, но процесс тот же, если у вас смешанные типы данных). Основываясь на вашем описании, каждый файл имеет только один набор данных. Если у вас есть несколько наборов данных, вы можете расширить этот процесс с помощью visititems() в h5py.

Примечание: код для создания файлов HDF5, используемый в примерах, находится в конце.

Все методы используютglob() для поиска файлов HDF5, используемых в следующих операциях.

Метод 1: создание внешних ссылок
В результате в новом файле HDF5 появятся 3 группы, каждая с внешнимссылка на исходные данные. Это не копирует данные, но обеспечивает доступ к данным во всех файлах по ссылкам в 1 файле.

with h5py.File('table_links.h5',mode='w') as h5fw:
    link_cnt = 0 
    for h5name in glob.glob('file*.h5'):
        link_cnt += 1
        h5fw['link'+str(link_cnt)] = h5py.ExternalLink(h5name,'/')   

Метод 2: Копирование данных «как есть»'
Копирует данные из каждого набора данных в исходном файле в новый файл с использованием исходного имени набора данных. Это требует, чтобы наборы данных в каждом файле имели разные имена. Данные не объединяются в один набор данных.

with h5py.File('table_copy.h5',mode='w') as h5fw:
    for h5name in glob.glob('file*.h5'):
        h5fr = h5py.File(h5name,'r') 
        dset1 = list(h5fr.keys())[0]
        arr_data = h5fr[dset1][:]
        h5fw.create_dataset(dset1,data=arr_data)   

Метод 3a: объединение всех данных в 1 набор данных фиксированного размера
Это копирует и объединяет данные из каждого набора данныхв исходном файле в один набор данных в новом файле. В этом примере нет ограничений на имена наборов данных. Кроме того, я изначально создаю большой набор данных и не изменяю размер. Предполагается, что строк достаточно для хранения всех объединенных данных. Тесты должны быть добавлены в производственную работу.

with h5py.File('table_merge.h5',mode='w') as h5fw:
    row1 = 0
    for h5name in glob.glob('file*.h5'):
        h5fr = h5py.File(h5name,'r') 
        dset1 = list(h5fr.keys())[0]
        arr_data = h5fr[dset1][:]
        h5fw.require_dataset('alldata', dtype="f",  shape=(50,5), maxshape=(100, 5) )
        h5fw['alldata'][row1:row1+arr_data.shape[0],:] = arr_data[:]
        row1 += arr_data.shape[0]

Метод 3b: Объединить все данные в 1 набор данных с изменяемым размером
Это похоже на метод выше. Однако я создаю изменяемый размер набора данных в зависимости от объема данных, которые считываются и добавляются.

with h5py.File('table_merge.h5',mode='w') as h5fw:
    row1 = 0
    for h5name in glob.glob('file*.h5'):
        h5fr = h5py.File(h5name,'r') 
        dset1 = list(h5fr.keys())[0]
        arr_data = h5fr[dset1][:]
        dslen = arr_data.shape[0]
        cols = arr_data.shape[1]
        if row1 == 0: 
            h5fw.create_dataset('alldata', dtype="f",  shape=(dslen,cols), maxshape=(None, cols) )
        if row1+dslen <= len(h5fw['alldata']) :
            h5fw['alldata'][row1:row1+dslen,:] = arr_data[:]
        else :
            h5fw['alldata'].resize( (row1+dslen, cols) )
            h5fw['alldata'][row1:row1+dslen,:] = arr_data[:]
        row1 += dslen

Для создания исходных файлов читайте выше:

for fcnt in range(1,4,1):
    fname = 'file' + str(fcnt) + '.h5'
    arr = np.random.random(50).reshape(10,5)
    with h5py.File(fname,'w') as h5fw :
        h5fw.create_dataset('data_'+str(fcnt),data=arr)
0 голосов
/ 08 октября 2019

Для тех, кто предпочитает использовать PyTables , я переделал мои примеры h5py, чтобы показать различные способы копирования данных между двумя файлами HDF5. В этих примерах используются те же примеры файлов HDF5, что и раньше. Каждый файл имеет только один набор данных. Если у вас несколько наборов данных, вы можете расширить этот процесс с помощью walk_nodes() в Pytables.

Все методы используют glob () для поиска файлов HDF5, используемых в следующих операциях.

Метод 1: Создание внешних ссылок
Подобно h5py, он создает 3 группы в новом файле HDF5, каждая из которых имеет внешнюю ссылку на исходные данные. Данные НЕ копируются.

import tables as tb
with tb.File('table_links_2.h5',mode='w') as h5fw:
    link_cnt = 0 
    for h5name in glob.glob('file*.h5'):
        link_cnt += 1
        h5fw.create_external_link('/', 'link'+str(link_cnt), h5name+':/')

Метод 2: Копировать данные «как есть»
Копирует данные из каждого набора данных в оригиналефайл в новый файл, используя исходное имя набора данных. Объект набора данных того же типа, что и исходный файл HDF5. В этом случае они являются массивами PyTable (потому что все столбцы имеют одинаковый тип). Наборы данных копируются с использованием имени в исходном HDF5, поэтому каждый из них должен иметь разные имена. Данные не объединяются в один набор данных.

with tb.File('table_copy_2.h5',mode='w') as h5fw:
    for h5name in glob.glob('file*.h5'):
        h5fr = tb.File(h5name,mode='r') 
        print (h5fr.root._v_children)
        h5fr.root._f_copy_children(h5fw.root)     

Метод 3a: Объединить все данные в 1 массив
Это копирует и объединяет данные из каждого набора данных висходный файл в одном наборе данных в новом файле. Опять же, данные сохраняются в виде массива PyTables. Нет ограничений на имена наборов данных. Сначала я читаю данные и добавляю их в массив Numpy. После обработки всех файлов массив Numpy копируется в массив PyTables. Этот процесс удерживает массив Numpy в памяти, поэтому может не работать для больших наборов данных. Вы можете избежать этого ограничения, используя Pytables EArray (Enlargeable Array). См. Метод 3b.

with tb.File('table_merge_2a.h5',mode='w') as h5fw:
    row1 = 0
    for h5name in glob.glob('file*.h5'):
        h5fr = tb.File(h5name,mode='r') 
        dset1 = h5fr.root._f_list_nodes()[0]
        arr_data = dset1[:]
        if row1 == 0 :
           all_data = arr_data.copy()
           row1 += arr_data.shape[0]
        else :
           all_data = np.append(all_data,arr_data,axis=0)
           row1 += arr_data.shape[0]
    tb.Array(h5fw.root,'alldata', obj=all_data )

Метод 3b: Объединить все данные в 1 Enlargeable EArray
Это похоже на метод выше, но сохраняет данные постепенно в EArray PyTables. Метод EArray.append() используется для добавления данных. Этот процесс уменьшает проблемы с памятью в методе 3а.

with tb.File('table_merge_2b.h5',mode='w') as h5fw:
    row1 = 0
    for h5name in glob.glob('file*.h5'):
        h5fr = tb.File(h5name,mode='r') 
        dset1 = h5fr.root._f_list_nodes()[0]
        arr_data = dset1[:]
        if row1 == 0 :
           earr = h5fw.create_earray(h5fw.root,'alldata', 
                                     shape=(0,arr_data.shape[1]), obj=arr_data )
        else :
           earr.append(arr_data)
        row1 += arr_data.shape[0]   

Метод 4: Объединить все данные в 1 таблицу
В этом примере показаны различия между h5py и PyTables . В h5py наборы данных могут ссылаться на np.arrays или np.recarrays - h5py работает с разными dtypes. В Pytables массивы (и CArrays и EArrays) ссылаются на nd.array данные, а таблицы ссылаются на np.recarray данные. В этом примере показано, как преобразовать данные nd.array из исходных файлов в данные np.recarray, подходящие для объектов таблицы. Также показано, как использовать Table.append() аналогично EArray.append() в методе 3b.

with tb.File('table_append_2.h5',mode='w') as h5fw:
    row1 = 0
    for h5name in glob.glob('file*.h5'):
        h5fr = tb.File(h5name,mode='r') 
        dset1 = h5fr.root._f_list_nodes()[0]
        arr_data = dset1[:]
        ds_dt= ([ ('f1', float), ('f2', float), ('f3', float), ('f4', float), ('f5', float) ])
        recarr_data = np.rec.array(arr_data,dtype=ds_dt)
        if row1 == 0: 
            data_table = h5fw.create_table('/','alldata', obj=recarr_data)
        else :
            data_table.append(recarr_data)
        h5fw.flush()
        row1 += arr_data.shape[0]
0 голосов
/ 02 октября 2019

Существует как минимум 3 способа объединить данные из отдельных файлов HDF5 в один файл:

  1. Использовать внешние ссылки для создания нового файла, который указывает на данные в других ваших файлах (требуется pytables)Модуль / tables)
  2. Скопируйте данные с помощью утилиты HDF Group: h5copy.exe
  3. Скопируйте данные с помощью Python (используя h5py или pytables)

Примервнешних ссылок доступно здесь:
https://stackoverflow.com/a/55399562/10462884
Здесь показано, как создавать ссылки и как их разыменовывать.

Документация для h5copy находится здесь:
https://support.hdfgroup.org/HDF5/doc/RM/Tools.html#Tools-Copy

Более сложное копирование с использованием h5py или pytables.

...