首页 > 解决方案 > 如何在 HDf5 文件中聚合 50 个数据集

问题描述

我有一个包含 2 组的 HDF5 文件,每组包含 50 个相同类型的 4D numpy 数组的数据集。我想将每组中的所有 50 个数据集组合成一个数据集。换句话说,我想要 2x1 数据集而不是 2 x 50 数据集。我怎样才能做到这一点?该文件大小为 18.4 Gb。我是处理大型数据集的新手。我正在使用 h5py 在 python 中工作。

谢谢!

标签: pythonhdf5h5py

解决方案


看看这个答案:如何合并多个 .h5 文件?- 方法 3b:将所有数据合并到 1 个 Resizeable Dataset中。它描述了一种将数据从多个 HDF5 文件复制到单个数据集中的方法。你想做类似的事情。唯一的区别是您的所有数据集都在 1 个 HDF5 文件中。

您没有说要如何堆叠 4D 数组。在我的第一个答案中,我将它们沿轴 = 3 堆叠。正如我在评论中所指出的,将合并的数据集创建为 5d 数组并沿第 5 轴(axis=4)堆叠数据更容易(也更简洁)。我喜欢这个有两个原因:代码更简单/更容易理解,2)axis=4 代表一个独特的数据集(而不是在 axis=3 上切片)更直观(对我来说)。

我写了一个独立的例子来演示这个过程。首先,它创建一些数据并关闭文件。然后它重新打开文件(只读)并为复制的数据集创建一个新文件。它遍历第一个文件中的组和数据集,并将数据复制到第二个文件中的合并数据集。首先是 5D 示例,然后是我的原始 4D 示例。

注意:这是一个简单的示例,适用于您的特定情况。如果您正在编写通用解决方案,它应该在盲目合并数据之前检查一致的形状和数据类型(我不这样做)。

创建示例数据的代码(2 组,每组 5 个数据集):

import h5py
import numpy as np

# Create a simple H5 file with 2 groups and 5 datasets (shape=a0,a1,a2,a3)
with h5py.File('SO_69937402_2x5.h5','w') as h5f1:
    
    a0,a1,a2,a3 = 100,20,20,10
    grp1 = h5f1.create_group('group1')
    for ds in range(1,6):
        arr = np.random.random(a0*a1*a2*a3).reshape(a0,a1,a2,a3)
        grp1.create_dataset(f'dset_{ds:02d}',data=arr)

    grp2 = h5f1.create_group('group2')
    for ds in range(1,6):
        arr = np.random.random(a0*a1*a2*a3).reshape(a0,a1,a2,a3)
        grp2.create_dataset(f'dset_{ds:02d}',data=arr)        
    

合并数据的代码(2组,每组1个5D数据集——我的偏好):

with h5py.File('SO_69937402_2x5.h5','r') as h5f1, \
     h5py.File('SO_69937402_2x1_5d.h5','w') as h5f2:
          
    # loop on groups in existing file (h5f1)
    for grp in h5f1.keys():
        # Create group in h5f2 if it doesn't exist
        print('working on group:',grp)
        h5f2.require_group(grp)
        # Loop on datasets in group
        ds_cnt = len(h5f1[grp].keys())
        for i,ds in enumerate(h5f1[grp].keys()):
            print('working on dataset:',ds)
            if 'merged_ds' not in h5f2[grp].keys():
            # If dataset doesn't exist in group, create it
            # Set maxshape so dataset is resizable
                ds_shape = h5f1[grp][ds].shape
                merge_ds = h5f2[grp].create_dataset('merged_ds',dtype=h5f1[grp][ds].dtype,
                                     shape=(ds_shape+(ds_cnt,)), maxshape=(ds_shape+(None,)) )

            # Now add data to the merged dataset 
            merge_ds[:,:,:,:,i] = h5f1[grp][ds]

合并数据的代码(2组,每组1个4D数据集):

with h5py.File('SO_69937402_2x5.h5','r') as h5f1, \
     h5py.File('SO_69937402_2x1_4d.h5','w') as h5f2:
          
    # loop on groups in existing file (h5f1)
    for grp in h5f1.keys():
        # Create group in h5f2 if it doesn't exist
        print('working on group:',grp)
        h5f2.require_group(grp)
        # Loop on datasets in group
        for ds in h5f1[grp].keys():
            print('working on dataset:',ds)
            if 'merged_ds' not in h5f2[grp].keys():
            # if dataset doesn't exist in group, create it
            # Set maxshape so dataset is resizable
                ds_shape = h5f1[grp][ds].shape
                merge_ds = h5f2[grp].create_dataset('merged_ds',data=h5f1[grp][ds],
                                     maxshape=[ds_shape[0],ds_shape[1],ds_shape[2],None])       
            else:
                # otherwise, resize the merged dataset to hold new values
                ds1_shape = h5f1[grp][ds].shape
                ds2_shape = merge_ds.shape
                merge_ds.resize(ds1_shape[3]+ds2_shape[3],axis=3)
                merge_ds[ :,:,:, ds2_shape[3]:ds2_shape[3]+ds1_shape[3] ] = h5f1[grp][ds]

推荐阅读