【问题标题】:how do I aggregate 50 datasets within an HDf5 file如何在 HDf5 文件中聚合 50 个数据集
【发布时间】:2021-12-24 11:25:58
【问题描述】:

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

谢谢!

【问题讨论】:

  • 你希望你的数据集完成后是什么样子?
  • 我想要 2 个数据集而不是 100 个数据集。每组 50 个都是同质的。
  • “同质”是什么意思?最终的数据集应该是一个 numpy 数组吗?

标签: python hdf5 h5py


【解决方案1】:

看看这个答案:How can I combine multiple .h5 file? - 方法 3b:将所有数据合并到 1 个可调整大小的数据集。它描述了一种将数据从多个 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]

【讨论】:

  • 需要考虑的两件事:1)将合并的数据集创建为 5d 数组,并沿第 5 轴(axis=4)堆叠数据。优点:您可以在创建数据集时调整它的大小,并且可以简化代码(或至少提高可读性)。 2) 考虑分块以提高 I/O 性能。调整块的大小以匹配您计划读取的形状(设置chunks=)。
  • 您好,感谢您的提示!实际上,4D 数组是沿轴 0 堆叠的 3D 数组的堆栈。我想……我总是对这些东西感到困惑。假设是这种情况,我想保留最后 3 个轴,那么在您的 2 组 1 个 4D 数据集的示例中,我是否将 0 换成 3?
  • 我实际上对在第三轴上附加的目的有点困惑?
  • 了解现有和所需数据集的数据模型(又名“模式”)是 HDF5 的关键。你的 cmets 有帮助。在我最初的回答中,我附加了axis=3,这是第4 轴。 (我刚刚选择了最后一个轴)。你看到我更新的答案了吗? (我将每个数据集沿轴 = 4 附加到 5D 数组中)恕我直言,这是最容易理解和使用的。 h5f1['group1']['dataset_0i'][:] 的数组映射到 h5f2['group1']['merged'][:,:,:,:,i-1] 的数据集(反之亦然)。如果您想创建 4D 合并数据集并沿轴 = 0 堆叠,我可以修改我的答案。告诉我。
猜你喜欢
  • 2016-01-02
  • 1970-01-01
  • 2017-03-21
  • 2017-11-03
  • 2017-10-02
  • 2016-06-02
  • 2021-11-09
  • 2015-12-06
  • 2018-11-20
相关资源
最近更新 更多