如何链接使用 Pandas 生成的 HDF5 文件?

Posted

技术标签:

【中文标题】如何链接使用 Pandas 生成的 HDF5 文件?【英文标题】:How to link HDF5 files generated with Pandas? 【发布时间】:2022-01-19 17:02:26 【问题描述】:

假设我们有一个文件夹,其中包含pandas.to_hdf 生成的 HDF5 文件。我想创建一个master.h5 文件,其中包含指向所有DataFrames 的外部链接。

根据h5py的文档,这样做的标准方法是

myfile = h5py.File('master.h5','w')
myfile['ext link'] = h5py.ExternalLink("some_sub_file.h5", "/path/to/resource")

但是pandas.to_hdf 生成的文件不仅包含datasets,还包含h5py.Groups。然后,您将如何设置外部链接以正常工作?

【问题讨论】:

【参考方案1】:

对 Pandas 和 HDF5 链接的额外研究揭示了一个有趣的发现:链接存在局限性(您可以在 Pandas 中创建它们,但 Pandas 无法访问链接数据)。换句话说,链接就在那里,并且可以与 HDFView、h5py 和 PyTables 一起正常工作。参考这些 GitHub 问题:

Pandas hdf functions should support the hdf5 ExternalLink functionality when reading/writing - Issue #6019 Presence of softlink in HDF5 file breaks HDFStore.keys() - Issue #20523 两者的状态似乎都是打开的。我的测试证实了之前报告的错误。

下面的代码显示了如何创建这两种链接类型。它还显示您在尝试访问链接数据时将收到的错误消息。 (错误消息是:KeyError: 'you cannot get attributes from this 'NoAttrs' instance。这是由于 HDF5 限制属性对链接的限制。HDFStore 节点具有一些必需的属性。当 Pandas 尝试读取属性时,结果是“NoAttrs”消息。

import pandas as pd
df1 = pd.DataFrame( "a": [1,2,3,4], "b": [11,12,13,14] )
print(df1.to_string())

# Create file 1 with simple dataframe
f1 = "test_1.hdf"
with pd.HDFStore(f1, mode="w") as  hdf1:
    hdf1.put("/key1", df1)

# Create file 2 with external link 
f2 = "test_extlink.hdf"
with pd.HDFStore(f2, mode="w") as hdf2:
    hdf2._handle.create_external_link(hdf2._handle.root, "extlink_key1", f"f1:/key1")
    print("Successful external link write")

with pd.HDFStore(f2, mode="r") as hdf2:
    print(hdf2.keys()) # Notice that [] (no keys) is printed
    # following lines will trigger the 'NoAttrs' error message
    # df2test = pd.read_hdf(f2,key="extlink_key1")
    # print(df2test.to_string())
    print("End external link read")

# Create file 3 with simple dataframe and symbolic (soft) link 
f3 = "test_symlink.hdf"    
with pd.HDFStore(f3, mode="w") as hdf3:
    hdf3.put("/key1", df1)
    hdf3._handle.create_soft_link(hdf3._handle.root, "symlink_key1", "/key1")
    print("Successful symbolic link write")
    
with pd.HDFStore(f3, mode="r") as hdf3:
    print(hdf3.keys()) # Notice that only ['key1'] is printed
    # following lines will trigger the 'NoAttrs' error message
    # df3test = pd.read_hdf(f3,key="symlink_key1")
    # print(df3test.to_string())
    print("End symbolic link read")    

【讨论】:

【参考方案2】:

链接可以指向 HDF5 数据结构(数据集或组)中的任何对象。文件是组的一种特殊形式;称为根组并用'/' 引用。因此,要链接到文件,请使用:h5py.ExternalLink(filename,'/')

您没有说是否需要每个文件中的每个数据框/数据集的链接,或者每个文件的链接。创建指向文件根组的链接更简单。如果您为数据集创建单独的链接,请确保指定唯一名称。

每种方法都有 2 个答案。这些问题并不是专门针对h5py.ExternalLink(),但我对每个问题的回答都使用了外部链接。请参阅以下答案:

HDF5 Attributes of External Links:在多个文件中创建指向根组的链接。 (每个文件只有 1 个数据集...但您的过程是相同的。) I/O Issues in Loading Several Large H5PY Files :在多个文件中创建指向多个数据集的链接。 (需要唯一的数据集名称才能“按原样”工作。如果名称不唯一,则可以修改。)

我修改了第二个答案 (70089964) 中的代码,以显示如何在 3 个文件中创建从主文件到根组的 3 个外部链接(其中每个文件有 5 个数据集)。

创建 3 个示例文件的代码:

import h5py
import numpy as np   
for fcnt in range(3):
    fname = f'file_fcnt+1.h5'
    with h5py.File(fname,'w') as h5fw:
        for dscnt in range(1,6,1):
            arr = np.random.random(10).reshape(5,2)
            h5fw.create_dataset(f'data_fcnt*10+dscnt:02',data=arr*dscnt)

创建从主文件到 3 个文件的链接的代码:

import h5py
fnames = ['file_1.h5','file_2.h5','file_3.h5']
with h5py.File(f'master_len(fnames)_links.h5','w') as h5fw:   
    for fname in fnames:
        with h5py.File(fname,'r') as h5fr:
                h5fw[fname] = h5py.ExternalLink(fname,'/')

【讨论】:

以上是关于如何链接使用 Pandas 生成的 HDF5 文件?的主要内容,如果未能解决你的问题,请参考以下文章

使用熊猫将 CSV 文件转换为 HDF5

如何在 R 中将保存在 pandas 中的数据框作为 HDF5 文件加载?

如何在 Python 中查找 HDF5 文件组/键?

如何将 Pandas 数据框写入 HDF5 数据集

Pandas HDF5 作为数据库

如何将 HDF5 文件转换为 Parquet 文件?