将HDF5文件读入numpy数组

37

我有以下代码可以将一个hdf5文件读取为numpy数组:

hf = h5py.File('path/to/file', 'r')
n1 = hf.get('dataset_name')
n2 = np.array(n1)

当我打印n2时,输出如下:

Out[15]:
array([[<HDF5 object reference>, <HDF5 object reference>,
        <HDF5 object reference>, <HDF5 object reference>...

我该如何读取HDF5对象引用以查看其中存储的数据?


你还可以看一下如何将ahdf5读入pandas dataframe,并从那里检查包含的信息,参见这里:https://dev59.com/M8Pra4cB1Zd3GeqPqNvi#74127100 - NeStack
6个回答

35

最简单的方法是使用HDF5数据集的.value属性。

>>> hf = h5py.File('/path/to/file', 'r')
>>> data = hf.get('dataset_name').value # `data` is now an ndarray.
您也可以对数据集进行切片,这会产生一个包含请求的数据的实际ndarray:
>>> hf['dataset_name'][:10] # produces ndarray as well

请记住,h5py 数据集在许多方面上的行为类似于 ndarray。因此,您可以将数据集本身不加修改地传递给大多数(如果不是所有)NumPy函数。例如,下面这个示例可以正常工作:np.mean(hf.get('dataset_name'))

编辑:

我最初误解了问题。问题不在于加载数字数据,而在于数据集实际上包含 HDF5 引用。这是一种奇怪的设置,并且在 h5py 中阅读起来有点棘手。您需要对数据集中的每个引用进行取消引用。我将仅展示其中一个。

首先,让我们创建一个文件和一个临时数据集:

>>> f = h5py.File('tmp.h5', 'w')
>>> ds = f.create_dataset('data', data=np.zeros(10,))

接下来,创建对它的引用并将一些引用存储在数据集中。

>>> ref_dtype = h5py.special_dtype(ref=h5py.Reference)
>>> ref_ds = f.create_dataset('data_refs', data=(ds.ref, ds.ref), dtype=ref_dtype)

然后你可以通过一种迂回的方式之一读取其中一个,方法是获取其名称,然后从引用该实际数据集的数据集中读取。

>>> name = h5py.h5r.get_name(ref_ds[0], f.id) # 2nd argument is the file identifier
>>> print(name)
b'/data'
>>> out = f[name]
>>> print(out.shape)
(10,)

虽然有些绕,但它似乎可行。TL;DR 是:获取所引用数据集的名称,并直接从该名称读取。

注意:

h5py.h5r.dereference 函数在这里似乎没有太大帮助,尽管名字是这样。它返回所引用对象的 ID。虽然可以直接从中读取,但在这种情况下很容易导致崩溃(我在这个人为例子中做了好几次)。获取名称并从那里读取会更容易。

注意2:

正如h5py 2.1 的发布说明中所述,使用 Dataset.value 属性已被弃用,应替换为使用适当的 mydataset[...]mydataset[()]

Dataset.value 属性最初于 h5py 1.0 中推出,现已弃用,并将在以后的版本中删除。此属性将整个数据集转储为 NumPy 数组。使用 .value 的代码应更新为使用 NumPy 索引,使用适当的 mydataset[...]mydataset[()]


我正在尝试这样做,但是当我打印data变量时仍然得到相同的HDF5对象引用 - e9e9s
看起来你可以使用 h5py.H5R 模块对数据集进行取消引用。你能试一下:h5py.h5r.dereference(hf['dataset_name']) 吗? - bnaecker
当我使用with h5py.File('path/to/file', 'r') as hdf:列出键时:ls = list(hdf.keys()) print('List of datasets in this file: \n', ls)我得到了List of datasets in this file: ['#refs#', 'data_set']。不确定这是否有帮助。 - e9e9s
"data_set" 是我正在尝试加载的内容。 - e9e9s
我仍然无法读取HDF5对象引用。很抱歉,我看不出你的示例与我的问题有何关联。我已经尝试了几天,并将在此发布答案,以便其他人不必经历这个过程。 - e9e9s
显示剩余5条评论

18

这里是一种直接的方法,可以将hdf5文件读取为numpy数组:

import numpy as np
import h5py

hf = h5py.File('path/to/file.h5', 'r')
n1 = np.array(hf["dataset_name"][:]) #dataset_name is same as hdf5 object name 

print(n1)

8
read_direct()
hf = h5py.File('path/to/file', 'r')
n1 = np.zeros(shape, dtype=numpy_type)
hf['dataset_name'].read_direct(n1)
hf.close()

如果你使用 %timeit 测试,结合这些步骤的速度仍然比 n1 = np.array(hf['dataset_name']) 更快。唯一的缺点是需要提前知道数据集的形状,这可以由数据提供者作为属性分配。


6
HDF5拥有一个简单的对象模型,用于存储数据集(大致相当于“文件数组”)并将其组织成组(类似于目录)。在这两种对象类型的基础上,还有更强大的功能需要层层理解。其中一个是“引用”。它是HDF5存储模型中的内部地址。h5py会为您完成所有工作,无需调用晦涩的例程,因为它尽可能地遵循类似于字典的接口(但对于引用,要使其透明化稍微复杂一些)。查找文档的位置是“对象和区域引用”。它指出,要访问由引用“ref”指向的对象,可以执行以下操作。
 my_object = my_file[ref]

在你的问题中,有两个步骤: 1. 获取参考资料 2. 获取数据集
# Open the file
hf = h5py.File('path/to/file', 'r')
# Obtain the dataset of references
n1 = hf['dataset_name']
# Obtain the dataset pointed to by the first reference
ds = hf[n1[0]]
# Obtain the data in ds
data = ds[:]

如果包含参考文献的数据集是二维的,那么您必须使用。
ds = hf[n1[0,0]]

如果数据集是标量,您必须使用
data = ds[()]

一次性获取所有数据集:
all_data = [hf[ref] for ref in n1[:]]

假设n1是一个一维数据集。对于二维数据集,这个想法仍然适用,但我没有找到简短的写法。
为了完全理解如何使用引用进行往返数据传输,我编写了一个简短的“写入程序”和一个简短的“读取程序”。
import numpy as np
import h5py

# Open file                                                                                    
myfile = h5py.File('myfile.hdf5', 'w')

# Create dataset                                                                               
ds_0 = myfile.create_dataset('dataset_0', data=np.arange(10))
ds_1 = myfile.create_dataset('dataset_1', data=9-np.arange(10))

# Create a data                                                                                
ref_dtype = h5py.special_dtype(ref=h5py.Reference)

ds_refs = myfile.create_dataset('ref_to_dataset', shape=(2,), dtype=ref_dtype)

ds_refs[0] = ds_0.ref
ds_refs[1] = ds_1.ref

myfile.close()

并且

import numpy as np
import h5py

# Open file                                                                                    
myfile = h5py.File('myfile.hdf5', 'r')

# Read the references                                                                          
ref_to_ds_0 = myfile['ref_to_dataset'][0]
ref_to_ds_1 = myfile['ref_to_dataset'][1]

# Read the dataset                                                                             
ds_0 = myfile[ref_to_ds_0]
ds_1 = myfile[ref_to_ds_1]

# Read the value in the dataset                                                                
data_0 = ds_0[:]
data_1 = ds_1[:]

myfile.close()

print(data_0)
print(data_1)

你会注意到,你不能使用方便易用的NumPy语法来引用数据集。这是因为HDF5引用不能用NumPy数据类型表示。它们必须逐个读取和写入。


5

大家好,这是我读取hdf5数据的方法,希望对你们有用。

with h5py.File('name-of-file.h5', 'r') as hf:
    data = hf['name-of-dataset'][:]

1

我尝试了之前提出的所有答案,但都不适用于我。例如,read_direct()方法会出错,提示“数据类型类别无法定义”。.value方法也不起作用。经过长时间的努力,我终于通过使用引用本身来获取numpy数组。

import numpy as np
import h5py
f = h5py.File('file.mat','r')
data2get = f.get('data2get')[:]

data = np.zeros([data2get.shape[1]])
for i in range(data2get.shape[1]):
    data[i]  = np.array(f[data2get[0][i]])[0][0]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接