【问题标题】:How to append a group in an H5 file to another H5 file without overwriting the same group in the second file如何将 H5 文件中的组附加到另​​一个 H5 文件而不覆盖第二个文件中的同一组
【发布时间】:2021-03-29 15:06:00
【问题描述】:

我有 2 个 H5 文件,file1.h5 和 file2.h5。部分文件内容如下:

文件1:

  • group1
    • 键名1
    • 键名2

文件2:

  • group1
    • 数据框1
    • 数据框3

这两个文件都可能包含其他组。我想将file1中group1的内容追加到file2中group1的内容,而不覆盖file2的原始内容,这样在处理结束时,file2的形式如下:

  • group1
    • dataframe1(file1 内容附加到 file2 原始内容)
    • 数据帧2
    • 数据框3

我知道h5py的copy方法可以将一组从一个H5文件复制到另一个,但是代码

import h5py
with h5py.File('file1.h5','r') as g:
    with h5py.File('file2.h5','a') as h:
        g.copy('group1',h)

将覆盖file2的原始内容,我不想这样做。

我知道我可以做到以下几点:

import h5py
import pandas as pd
with h5py.File('file1.h5','r') as g:
    keynames = g['group1'].keys()
for name in keynames:
    df = pd.read_hdf('file1.h5',key = 'group1/' + name)
    df.to_hdf('file2.h5',key = 'group1/' + name,mode = 'a',append = True)

是否有一种更简单、更方便的方法来执行此操作,类似于 h5py 复制方法?

【问题讨论】:

  • 我认为两个文件的dataframe1 必须在适当的轴上加载和连接。然后,如果有办法从file2 中删除dataframe1(查看文档),请将新数组写入该组。在最坏的情况下,将其写入不同的数据集名称。虽然可以定义一个可以增长的数据集,但通常您无法更改现有数据集的大小。

标签: python copy append h5py


【解决方案1】:

我不知道这是否更简单,但它是一个复制数据而不覆盖现有组和数据集的过程。它使用h5_object.visititems() 递归地访问组中的所有对象及其子组。这一次检索一个组和数据集。您编写“访问者函数”以在找到对象时对其进行操作。

我的大部分示例创建了 2 个包含组和数据集的文件(用于演示)。关注def visitor_func(name, node)。这就是工作完成的地方。我包含了额外的打印语句以显示正在发生的事情。我的访问者函数执行以下操作:

  1. 它检查文件 1 中的对象是否在文件 2 中。如果是,则跳过。
  2. 如果对象(组或数据集)不在文件 2 中,则将对象复制到文件 2。
  3. 默认情况下,该组中的所有对象都将被递归复制(因此您可以获得数据集和子组)。
  4. 对于数据集,使用name=参数将其复制到同一个 File2 中的位置/路径。

请注意,此代码不会将常见数据集的数据从文件 1 附加到文件 2。例如,两个文件都有一个数据集“/group2/ds1”。我不会复制这些数据。我需要更多地了解您的数据结构来编写要附加的代码。如果要将数据附加到 File2 中的现有数据集,则需要考虑几件事。例如:

  • 两个数据集必须具有相同的 dtype(int、float 等或 recarray)。
  • 两个数据集必须具有兼容的形状。
  • 您需要定义追加方式(沿哪个数组轴?)
  • 如果您想稍后添加数据,则需要(先验)特殊步骤来创建可调整大小的数据集。您需要使用maxshape=() 参数。可调整大小的数据集也需要启用分块存储。 (我认为使用maxshape 时会设置默认块大小。)

我的示例数据集突出了挑战。所有数据集都是 (10,10) ndarrays 的浮点数。那么,我应该如何将文件 1 中的 (10,10) 数组附加到文件 2 中的 (10,10) 数组中?结果应该是:

  • A) 一个 (20,10) 数组(沿轴 = 0),或
  • B) 一个 (10,20) 数组(沿轴 = 1),或
  • C) (10,10,2) 数组(沿新轴=2)

一切都是合乎逻辑且有效的。 “正确答案”取决于您的数据架构。

查看此答案中的方法 3a 和 3b 以获得一些想法:How can I combine multiple .h5 file?

示例代码如下:

import h5py
import numpy as np

def visitor_func(name, node):
    print('working on name:', name, ', path=',node.parent.name)
    if isinstance(node,h5py.Group):
        print ('h5f1 object found:',name,'is a group')
    elif isinstance(node,h5py.Dataset):
        print ('h5f1 object found:',name,'is a dataset')
 
    if h5f2.__contains__(name):
        print ('Object:', name, 'also in File2. Skipping...\n')
    else:
        print ('Object:', name, 'NOT in File2. Copying...\n')
        h5f1.copy(node,h5f2,name=name)
        

# Create File1 with 2 Groups with 2 Datasets in each 
with h5py.File('SO_65365873_1.h5', mode='w') as h5f1:
    h5f1.create_group('/group1')
    arr = np.random.random((10,10))
    h5f1.create_dataset('/group1/df1', data=arr)
    arr = np.random.random((10,10))
    h5f1.create_dataset('/group1/df2',data=arr)
    h5f1.create_group('/group2')
    arr = np.random.random((10,10))
    h5f1.create_dataset('/group2/df1', data=arr)
    arr = np.random.random((10,10))
    h5f1.create_dataset('/group2/df2',data=arr)

# Create File2 with 1 Group with 2 Datasets    
with h5py.File('SO_65365873_2.h5', mode='w') as h5f2:
    h5f2.create_group('/group2')
    arr = np.random.random((10,10))
    h5f2.create_dataset('/group2/df1', data=arr)
    arr = np.random.random((10,10))
    h5f2.create_dataset('/group2/df3',data=arr)

# Copy data from File1 to File2 WITHOUT overwriting
with h5py.File('SO_65365873_1.h5', mode='r') as h5f1:
    with h5py.File('SO_65365873_2.h5', mode='a') as h5f2:
        h5f1.visititems(visitor_func)

【讨论】:

    猜你喜欢
    • 2021-05-08
    • 2014-05-20
    • 2020-07-15
    • 2021-02-15
    • 2014-05-31
    • 2019-08-15
    • 2016-04-02
    • 1970-01-01
    • 2017-08-07
    相关资源
    最近更新 更多