У меня есть следующий код для чтения файла 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
для просмотра сохраненных в нем данных?
Самое простое - использовать атрибут .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
кажется бесполезной здесь, несмотря на название. Он возвращает идентификатор ссылочного объекта. Это можно прочитать напрямую, но в этом случае очень легко вызвать сбой (я сделал это несколько раз в этом надуманном примере здесь). Получение имени и чтения из этого намного проще.
Вот прямой подход к чтению файла 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)
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. Их нужно читать и писать по одному.
Привет, это то, как я использую для чтения данных hdf5, надеюсь, что это может быть полезно для вас.
with h5py.File('name-of-file.h5', 'r') as hf:
data = hf['name-of-dataset'][:]
HDF5 object reference
когда я печатаю переменнуюdata
h5ls
илиh5dump
для файла. В этом случае я не знаю, как вы можете читать из ссылочного набора данных вh5py
.