【问题标题】:Creating a dataset from multiple hdf5 groups从多个 hdf5 组创建数据集
【发布时间】:2021-02-11 00:04:55
【问题描述】:

从多个 hdf5 组创建数据集

组代码

np.array(hdf.get('all my groups'))

然后我添加了用于从组创建数据集的代码。

with h5py.File('/train.h5', 'w') as hdf:
hdf.create_dataset('train', data=one_T+two_T+three_T+four_T+five_T)

错误信息是

ValueError: operands could not be broadcast together with shapes(534456,4) (534456,14)

除了列长不同之外,每组中的数字都相同。 5 个单独的组到一个数据集。

【问题讨论】:

  • 当你说“我所有的组”时,你是指数据集还是组? HDF5 将数据存储在数据集中。组类似于文件夹。我假设您想将来自多个数据集(在 1 个文件中)的数据连接到另一个文件中的 1 个数据集中。如果是这样,这可以通过循环组键(数据集名称)来完成,然后将每个数据集复制到一个 numpy 数组,将数组写入新文件/数据集并为每个数据集重复。
  • 是的,就是这样。
  • 您有不同形状的数据集:(534456,4) 和 (534456,14)。其他数据集的形状是否兼容(534456,#)?如果是这样,我假设新数据集将沿 1 轴附加,结果形状为 (534456,n1+n2+n3+n4+n5)。正确的?此外,所有数据集都需要具有相同的 dtype(所有浮点数或整数等)。你需要一个如何做到这一点的例子吗?
  • 是的,拜托,它们是一样的。您在 1 轴上是正确的。是的,它们确实具有相同的 Dtype
  • 举个例子就太好了,谢谢。

标签: python hdf5 h5py


【解决方案1】:

这个答案解决了 OP 在 cmets 中对我的第一个答案的请求(“一个例子是 ds_1 所有列,ds_2 前两列,ds_3 第 4 和 6 列,ds_4 所有列”)。过程非常相似,但输入比第一个答案“稍微复杂一些”。因此,我使用了不同的方法来定义要复制的数据集名称和列。区别:

  • 第一个解决方案从“keys()”迭代数据集名称(完全复制每个数据集,附加到新文件中的数据集)。新数据集的大小是通过对所有数据集的大小求和来计算的。
  • 第二种解决方案使用 2 个列表来定义 1) 数据集名称 (ds_list) 和 2) 要从每个数据集中复制的关联列(col_list 是列表中的一个)。新数据集的大小是通过对col_list 中的列数求和来计算的。我使用“花式索引”来提取使用col_list 的列。
  • 您决定如何执行此操作取决于您的数据。
  • 注意:为简单起见,我删除了 dtype 和 shape 测试。您应该包含这些内容以避免“现实世界”问题的错误。

代码如下:

# Data for file1
arr1 = np.random.random(120).reshape(20,6)
arr2 = np.random.random(120).reshape(20,6)
arr3 = np.random.random(120).reshape(20,6)
arr4 = np.random.random(120).reshape(20,6)

# Create file1 with 4 datasets
with h5py.File('file1.h5','w') as h5f :
    h5f.create_dataset('ds_1',data=arr1)
    h5f.create_dataset('ds_2',data=arr2)
    h5f.create_dataset('ds_3',data=arr3)
    h5f.create_dataset('ds_4',data=arr4)
 
# Open file1 for reading and file2 for writing
with h5py.File('file1.h5','r') as h5f1 , \
     h5py.File('file2.h5','w') as h5f2 :

# Loop over datasets in file1 to get dtype and rows (should test compatibility)        
     for i, ds in enumerate(h5f1.keys()) :
        if i == 0:
            ds_0_dtype = h5f1[ds].dtype
            n_rows = h5f1[ds].shape[0]
            break

# Create new empty dataset with appropriate dtype and size
# Use maxshape parameter to make resizable in the future

    ds_list = ['ds_1','ds_2','ds_3','ds_4']
    col_list =[ [0,1,2,3,4,5], [0,1], [3,5], [0,1,2,3,4,5] ]
    n_cols = sum( [ len(c) for c in col_list])
    h5f2.create_dataset('combined', dtype=ds_0_dtype, shape=(n_rows,n_cols), maxshape=(n_rows,None))
    
# Loop over datasets in file1, read data into xfer_arr, and write to file2        
    first = 0  
    for ds, cols in zip(ds_list, col_list) :
        xfer_arr = h5f1[ds][:,cols]
        last = first + xfer_arr.shape[1]
        h5f2['combined'][:, first:last] = xfer_arr[:]
        first = last

【讨论】:

    【解决方案2】:

    给你;将值从 file1 中的 3 个数据集复制到 file2 中的单个数据集的简单示例。我包括了一些测试来验证兼容的 dtype 和 shape。创建 file1 的代码包含在顶部。代码中的注释应该解释这个过程。我有另一篇文章展示了在 2 个 HDF5 文件之间复制数据的多种方法。看到这个帖子:How can I combine multiple .h5 file?

    import h5py
    import numpy as np
    import sys
    
    # Data for file1
    arr1 = np.random.random(80).reshape(20,4)
    arr2 = np.random.random(40).reshape(20,2)
    arr3 = np.random.random(60).reshape(20,3)
    
    #Create file1 with 3 datasets
    with h5py.File('file1.h5','w') as h5f :
        h5f.create_dataset('ds_1',data=arr1)
        h5f.create_dataset('ds_2',data=arr2)
        h5f.create_dataset('ds_3',data=arr3)
     
    # Open file1 for reading and file2 for writing
    with h5py.File('file1.h5','r') as h5f1 , \
         h5py.File('file2.h5','w') as h5f2 :
    
    # Loop over datasets in file1 and check data compatiblity         
        for i, ds in enumerate(h5f1.keys()) :
            if i == 0:
                ds_0 = ds
                ds_0_dtype = h5f1[ds].dtype
                n_rows = h5f1[ds].shape[0]
                n_cols = h5f1[ds].shape[1]
            else:
                if h5f1[ds].dtype != ds_0_dtype :
                    print(f'Dset 0:{ds_0}: dtype:{ds_0_dtype}')
                    print(f'Dset {i}:{ds}: dtype:{h5f1[ds].dtype}')
                    sys.exit('Error: incompatible dataset dtypes')
    
                if h5f1[ds].shape[0] != n_rows :
                    print(f'Dset 0:{ds_0}: shape[0]:{n_rows}')
                    print(f'Dset {i}:{ds}: shape[0]:{h5f1[ds].shape[0]}')
                    sys.exit('Error: incompatible dataset shape')
    
                n_cols += h5f1[ds].shape[1]
            prev_ds = ds    
    
    # Create new empty dataset with appropriate dtype and size
    # Using maxshape paramater to make resizable in the future
        h5f2.create_dataset('ds_123', dtype=ds_0_dtype, shape=(n_rows,n_cols), maxshape=(n_rows,None))
        
    # Loop over datasets in file1, read data into xfer_arr, and write to file2        
        first = 0
        for ds in h5f1.keys() :
            xfer_arr = h5f1[ds][:]
            last = first + xfer_arr.shape[1]
            h5f2['ds_123'][:, first:last] = xfer_arr[:]
            first = last
    

    【讨论】:

    • 谢谢。一个小问题是组合时数据集的顺序。就像您订购了它们 ds_1、ds_2 和 ds_3。将它们组合起来是可行的,但创建的 ds_123 数据集看起来是随机顺序的。 ds_2、ds_1、ds_3。有什么想法吗?
    • 我没有定义读取顺序。数据集按h5f1.keys() 生成名称/键的顺序进行处理。 (在我的测试中,它们按 1、2、3 的顺序处理;但这可能是运气不好)。如果您先验地知道名称,则使用列表处理此问题:ds_list = ['ds_1', 'ds_2', ds_3'],然后将h5f1.keys() 替换为ds_list,然后您就设置好了。如果您不知道名称,则很难控制顺序。要按字母顺序处理,请从键创建一个列表,然后在列表上使用.sort()
    • 谢谢,我知道名单。是否可以从特定列表中删除列?
    • 请澄清。您想从每个数据集中复制字段(列)的子集吗?例如,来自 ds_1 的 Col_1 和 Col_2,来自 ds_2 的 Col_2,以及来自 ds_3 的 Col_3 和 Col_4?如果是这样,您可以通过修改 xfer_arr 切片来实现。使用[:] 读取整个数据集。要仅读取二维数组的前 2 列,请更改为 [0:2,:]。如果你这样做,你需要精确地使用切片表示法(读取和写入)。
    • 一个例子是 ds_1 所有列,ds_2 前两列,ds_3 第 4 和 6 列,ds_4 所有列。
    猜你喜欢
    • 2018-01-05
    • 1970-01-01
    • 2015-09-07
    • 2021-11-05
    • 2012-11-22
    • 2021-11-09
    • 2017-11-03
    • 2019-10-13
    • 2012-06-13
    相关资源
    最近更新 更多