Чтение структуры данных Matlab в массивы numpy

У меня есть набор MAT-файлов, который содержит matlab struct. Структура имеет кучу массивов. Я хотел бы открыть файл и перенести их все в массивы. Пока я написал следующий код:

import h5py
>>> fs = h5py.File('statistics_VAD.mat','r')
>>> list(fs.keys())
['#refs#', 'data']
>>> 
>>> fs['data'].visititems(lambda n,o:print(n, o))
C <HDF5 dataset "C": shape (100, 1), type "|O">
P <HDF5 dataset "P": shape (100, 1), type "|O">
V <HDF5 dataset "V": shape (100, 1), type "|O">
Wn <HDF5 dataset "Wn": shape (100, 1), type "|O">
X <HDF5 dataset "X": shape (100, 1), type "|O">
a <HDF5 dataset "a": shape (100, 1), type "|O">
dn <HDF5 dataset "dn": shape (100, 1), type "|O">
>>> struArray = fs['data']
>>> print(struArray['P'])
<HDF5 dataset "P": shape (100, 1), type "|O">

Я не знаю, как передать HDF5 dataset "P" в массив numpy. Любое предложение будет оценено


person Dalek    schedule 28.02.2021    source источник
comment
Что делает arr=struArray['P'][:]?   -  person hpaulj    schedule 28.02.2021
comment
@hpaulj вывод >>> arr=struArray['P'][:] >>> arr array([[<HDF5 object reference>], [<HDF5 object reference>], [<HDF5 object reference>], [<HDF5 object reference>], [<HDF5 object reference>], [<HDF5 object reference>], ....   -  person Dalek    schedule 28.02.2021
comment
Эти «ссылки на объекты», вероятно, являются элементами группы refs, но я не знаю, может ли h5py получить их для вас. scipy.io.loadmat может работать с файлом .mat более старого стиля, но даже в этом случае результат может содержать «непрозрачные» элементы. Не все, что Matlab сохраняет в файл, можно перевести в numpy.   -  person hpaulj    schedule 28.02.2021
comment
@hpaulj, так как я использовал эту командную строку в Matlab для сохранения данных save( 'statistics_VAD.mat','data', '-v7.3');, я получаю эту ошибку, используя scipy.io.loadmat: mat_contents = sio.loadmat(mat_fname) raise NotImplementedError('Please use HDF reader for matlab v7.3 files') NotImplementedError: Please use HDF reader for matlab v7.3 files   -  person Dalek    schedule 28.02.2021
comment
Я не рекомендовал вам использовать этот ридер.   -  person hpaulj    schedule 28.02.2021
comment
@hpaulj вы говорите, что мне лучше вернуться в Matlab, чтобы проанализировать данные? :)   -  person Dalek    schedule 28.02.2021
comment
Я понятия не имею, что находится в вашей структуре MATLAB. loadmat может обрабатывать файлы, написанные в стиле до версии 7.3, при условии, что они содержат только структуру и ячейки с простыми матричными элементами, хотя результатом может быть сложное наслоение структурированных и объектных массивов dtype. Другие SO исследовали файлы 7.3 с разной степенью успеха.   -  person hpaulj    schedule 28.02.2021
comment
@hpaulj все элементы в моей структуре Matlab являются массивами. Можете ли вы предложить другой SO в python, который позволил бы мне исследовать и использовать данные, сохраненные в Matlab?   -  person Dalek    schedule 28.02.2021
comment
Нет. Вы можете сделать свой собственный поиск! Но будьте осторожны с некоторыми из старых постов. MATLAB изменил свой формат HDF5 один или несколько раз. У меня есть только Octave для экспериментов, и я не знаю, поспевает ли он за изменениями MATLAB в этой области.   -  person hpaulj    schedule 28.02.2021
comment
@Dalek, работа с данными Matlab, сохраненными в формате HDF5, может быть головной болью, в основном потому, что Matlab использует множество ссылок на объекты, и вам нужно самостоятельно разобраться в схеме. Почитал комментарии, вы на верном пути. Пока мы знаем, что fs['data']['P'] — это массив ссылок на объекты формы (100,1). Объект можно использовать для ссылки на другой объект в файле или для хранения вложенного массива — массива массивов. Что вы получите, если print (struArray['P'][1,1])? Знание этого может помочь вывести схему.   -  person kcw78    schedule 01.03.2021
comment
@ kcw78 Я получаю этот вывод по вашему предложению ValueError: Index (1) out of range (0-0), но с помощью этой команды я получил >>> print (struArray['P'][1]) [<HDF5 object reference>] .   -  person Dalek    schedule 01.03.2021
comment
Используйте [0,0], чтобы получить первый элемент. Форма (100,1)   -  person hpaulj    schedule 01.03.2021
comment
@hpaulj Он снова возвращает аналогичный результат >>> print (struArray['P'][0,0]) <HDF5 object reference>.   -  person Dalek    schedule 01.03.2021
comment
@Dalek извините за ошибку индексации - я не обращал внимания. Чтобы получить ссылочный объект, вы используете его с вашим файловым объектом (аналогично именам групп/наборов данных). Итак, для этого объекта: struArray['P'][0,0] объект, на который ссылаются, fs [ struArray['P'][0,0] ]. Чтобы продемонстрировать поведение, я собрал небольшой пример и опубликовал его в качестве ответа. (Это не точный ответ, но он показывает процесс, используемый для получения объектов, а затем чтения разыменованных данных. Я также добавил код для ссылки на регион (для полноты).   -  person kcw78    schedule 01.03.2021


Ответы (1)


Код ниже — это пример, упомянутый в моем комментарии (от 2021-03-01). Он создает 2 набора данных из массивов NumPy, затем набор данных с 2 ссылками на объекты, по 1 на каждый набор данных. Затем показано, как использовать ссылки на объекты для доступа к данным. Второй набор данных со ссылками на регионы также сделан для полноты.

Обратите внимание, как h5f[] используется дважды: внутренний получает объект, а внешний получает данные из ссылки на объект. Это тонкость, которая сбивает пользователей с толку.

import numpy as np
import h5py

with h5py.File('SO_66410592.h5','w') as h5f :
    # Create 2 datasets using numpy arrays
    arr = np.arange(100).reshape(20,5)
    h5f.create_dataset('array1',data=arr)    
    arr = np.arange(100,0,-1).reshape(20,5)
    h5f.create_dataset('array2',data=arr) 
    
    # Create a dataset of OBJECT references: 
    h5f.create_dataset('O_refs', (10,), dtype=h5py.ref_dtype)
    h5f['O_refs'][0] = h5f['array1'].ref
    print (h5f['O_refs'][0])
    print (h5f[ h5f['O_refs'][0] ])
    print (h5f[ h5f['O_refs'][0] ][0,:])
    h5f['O_refs'][1] = h5f['array2'].ref
    print (h5f['O_refs'][1])
    print (h5f[ h5f['O_refs'][1] ])
    print (h5f[ h5f['O_refs'][1] ][-1,:])

    # Create a dataset of REGION references: 
    h5f.create_dataset('R_refs', (10,), dtype=h5py.regionref_dtype)
    h5f['R_refs'][0] = h5f['array1'].regionref[0,:]
    print (h5f['R_refs'][0])
    print (h5f[ h5f['R_refs'][0] ])    
    print (h5f[ h5f['R_refs'][0] ] [ h5f['R_refs'][0] ]) 
    h5f['R_refs'][1] = h5f['array2'].regionref[-1,:]
    print (h5f['R_refs'][1])
    print (h5f[ h5f['R_refs'][1] ])    
    print (h5f[ h5f['R_refs'][1] ] [ h5f['R_refs'][1] ]) 
person kcw78    schedule 01.03.2021