首页 > 解决方案 > 如何合并多个 .h5 文件?

问题描述

网上可用的一切都太复杂了。我的数据库很大,我将其部分导出。我现在有三个 .h5 文件,我想将它们组合成一个 .h5 文件以供进一步工作。我该怎么做?

标签: hdf5h5pypytableshdf

解决方案


这些示例展示了如何使用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,'/')   

方法 2a:“按原样”复制数据
(2020 年 5 月 26 日更新:此.copy()方法适用于所有数据集。)
这会将原始文件中每个数据集的数据复制到使用原始数据集名称的新文件中。它循环复制所有根级数据集。这要求每个文件中的数据集具有不同的名称。数据不会合并到一个数据集中。

with h5py.File('table_copy.h5',mode='w') as h5fw:
    for h5name in glob.glob('file*.h5'):
        h5fr = h5py.File(h5name,'r') 
        for obj in h5fr.keys():        
            h5r.copy(obj, h5fw)       

方法 2b:“按原样”复制数据
(这是我最初的答案,在我知道该.copy()方法之前。)
这会将原始文件中每个数据集的数据复制到使用原始数据集名称的新文件中。这要求每个文件中的数据集具有不同的名称。数据不会合并到一个数据集中。

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)

推荐阅读