Считать файл HDF5 в массив

1

У меня есть следующий код для чтения файла 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 object reference для просмотра сохраненных в нем данных?

Теги:
numpy
hdf5
h5py

4 ответа

3

Самое простое - использовать атрибут .value набора данных HDF5.

>>> 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')).

EDIT:

Я неправильно понял вопрос. Проблема заключается не в загрузке числовых данных, а в том, что набор данных действительно содержит ссылки 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 кажется бесполезной здесь, несмотря на название. Он возвращает идентификатор ссылочного объекта. Это можно прочитать напрямую, но в этом случае очень легко вызвать сбой (я сделал это несколько раз в этом надуманном примере здесь). Получение имени и чтения из этого намного проще.

  • 0
    Я пытаюсь это, но я все еще получаю ту же HDF5 object reference когда я печатаю переменную data
  • 0
    Ах, я думаю, что знаю, что происходит. Набор данных, который вы пытаетесь загрузить, на самом деле состоит из ссылок HDF5. Это не числовые данные. Вы можете проверить это, выполнив h5ls или h5dump для файла. В этом случае я не знаю, как вы можете читать из ссылочного набора данных в h5py .
Показать ещё 7 комментариев
0

Вот прямой подход к чтению файла 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)
0

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[:]

Если набор данных, содержащий ссылки, является 2D, например, вы должны использовать

ds = hf[n1[0,0]]

Если набор данных является скалярным, вы должны использовать

data = ds[()]

Чтобы сразу получить все наборы данных:

all_data = [hf[ref] for ref in n1[:]]

предполагая 1D набор данных для n1. Для 2D идея держится, но я не вижу короткого пути ее записи.

Чтобы получить полное представление о том, как обойти данные со ссылками, я написал короткую "программу-писатель" и короткую "программу чтения":

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. Их нужно читать и писать по одному.

0

Привет, это то, как я использую для чтения данных hdf5, надеюсь, что это может быть полезно для вас.

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню