Как различать наборы данных HDF5 и группы с h5py?

я использую пакет Python h5py (версия 2.5.0) для доступа к моим файлам hdf5.

Я хочу просмотреть содержимое файла и сделать что-то с каждым набором данных.

С помощью visit способ:

import h5py

def print_it(name):
    dset = f[name]
    print(dset)
    print(type(dset))


with h5py.File('test.hdf5', 'r') as f:
    f.visit(print_it)

для тестового файла я получаю:

<HDF5 group "/x" (1 members)>
<class 'h5py._hl.group.Group'>
<HDF5 dataset "y": shape (100, 100, 100), type "<f8">
<class 'h5py._hl.dataset.Dataset'>

что говорит мне, что в файле есть набор данных и группа. Однако нет очевидного способа, кроме использования type() чтобы различать наборы данных и групп. The h5py документация к сожалению ничего не говорит об этой теме. Они всегда предполагают, что вы заранее знаете, что такое группы и что такое наборы данных, например, потому что они сами создали наборы данных.

Я хотел бы иметь что-то вроде:

f = h5py.File(..)
for key in f.keys():
    x = f[key]
    print(x.is_group(), x.is_dataset()) # does not exist

как я могу различать группы и наборы данных при чтении неизвестного файла hdf5 в Python с помощью h5py? Как я могу получить список всех наборов данных, всех групп, всех ссылок?

4 ответов


к сожалению, в api h5py нет встроенного способа проверить это, но вы можете просто проверить тип элемента с помощью is_dataset = isinstance(item, h5py.Dataset).

чтобы перечислить все содержимое файла (за исключением атрибутов файла), вы можете использовать Group.visititems с вызываемым, который принимает имя и экземпляр элемента.


в то время как ответы Галла и Джеймса Смита указывают на решение в целом, обход через иерархическую структуру HDF и фильтрацию всех наборов данных все еще необходимо сделать. Я сделал это, используя yield from, который доступен в Python 3.3+, который работает довольно хорошо и представить его здесь.

import h5py

def h5py_dataset_iterator(g, prefix=''):
    for key in g.keys():
        item = g[key]
        path = '{}/{}'.format(prefix, key)
        if isinstance(item, h5py.Dataset): # test for dataset
            yield (path, item)
        elif isinstance(item, h5py.Group): # test for group (go down)
            yield from h5py_dataset_iterator(item, path)

with h5py.File('test.hdf5', 'r') as f:
    for (path, dset) in h5py_dataset_iterator(f):
        print(path, dset)

поскольку h5py использует словари python в качестве метода выбора для взаимодействия, вам нужно использовать функцию "values()" для фактического доступа к элементам. Таким образом, вы можете использовать фильтры списка:

datasets = [item for item in f["Data"].values() if isinstance(item, h5py.Dataset)]

выполнение этого рекурсивно должно быть достаточно простым.


Я предпочитаю это решение. Он находит список всех объектов в файле hdf5 "h5file", затем сортирует их по классу, аналогично тому, что было упомянуто ранее, но не таким лаконичным образом:

import h5py
fh5 = h5py.File(h5file,'r')
fh5.visit(all_h5_objs.append)
all_groups   = [ obj for obj in all_h5_objs if isinstance(fh5[obj],h5py.Group) ]
all_datasets = [ obj for obj in all_h5_objs if isinstance(fh5[obj],h5py.Dataset) ]