чтение файла v 7.3 mat в python

Я пытаюсь прочитать файл Matlab со следующим кодом

import scipy.io
mat = scipy.io.loadmat('test.mat')

и это дает мне следующую ошибку

raise NotImplementedError('Please use HDF reader for matlab v7.3 files')
NotImplementedError: Please use HDF reader for matlab v7.3 files

так что у кого-нибудь может быть такая же проблема и может понравиться любой образец кода

Благодарность


person Shan    schedule 26.06.2013    source источник
comment
связанные с: stackoverflow.com/q/874461/1714410   -  person Shai    schedule 21.12.2016


Ответы (9)


Попробуйте использовать модуль h5py

import h5py
with h5py.File('test.mat', 'r') as f:
    f.keys()
person Shai    schedule 26.06.2013
comment
да, но существует множество структур, и я понятия не имею, как это читать, - person Shan; 27.06.2013
comment
f.keys() должен дать вам имена переменных, хранящихся в 'test.mat'. Вы можете получить доступ к f['s'][0].keys()? Предполагая, что s - это имя массива структур, который вы сохранили, это должно дать вам список полей s. - person Shai; 27.06.2013
comment
нет, я не могу получить к нему доступ, точнее, я пытаюсь прочитать файл mat, указанный на следующем веб-сайте, ufldl. stanford.edu/housenumbers, в файле train.tar.gz есть файл mat с именем digitStruct.mat - person Shan; 27.06.2013
comment
Этот ответ на самом деле не дает достаточного фона для фактического использования файла mat таким образом. Конечно, файлы можно открывать, но с scipy.io.loadmat файл представлен в прозрачных структурах данных (а именно словарях и множественных массивах). Ответ был бы значительно улучшен, если бы он также указывал, как на самом деле получить доступ к структурам данных HDF. - person aestrivex; 21.05.2015
comment
Этот фрагмент кода даст вам словарь. Извлекая данные, связанные с ключами, которые являются именами переменных, мы можем получить структуры данных, подобные массивам. например <HDF5 dataset "fv": shape (18000, 9475), type "<f4">. Строка или столбец могут быть доступны непосредственно из этой структуры данных, или мы можем легко преобразовать их в массив numpy: np.array(data_structure). - person lenhhoxung; 29.12.2016
comment
Я создал библиотеку для удобной загрузки .mat: github.com/skjerns/mat7.3 , он загружается в собственные типы Python. Установить с pip install mat73 - person skjerns; 17.12.2019
comment
Спустя годы этот ответ по-прежнему набирает большинство голосов, несмотря на то, что он совершенно бесполезен, поскольку на самом деле не говорит вам, как использовать результат f.keys() (спойлер, вы получаете KeysView(<HDF5 file "test.mat" (mode r+)>), который совершенно бесполезен. Вы могли хотя бы сказали преобразовать непонятный объект в список, чтобы вы могли видеть, какие на самом деле ключи. Все это просто показывает, насколько бессмысленно непонятный h5py на самом деле. Почему это все еще стандартная библиотека HDF5, мне не по силам. - person ThatNewGuy; 01.04.2021

import h5py
import numpy as np
filepath = '/path/to/data.mat'
arrays = {}
f = h5py.File(filepath)
for k, v in f.items():
    arrays[k] = np.array(v)

вы должны закончить свои данные в arrays dict, если у вас нет структур MATLAB, я подозреваю. Надеюсь, поможет!

person norok2    schedule 01.02.2017
comment
какую проблему вы наблюдаете? Вы проверили, что MATLAB (или октава) может открыть файл? - person norok2; 01.03.2018
comment
Да, я могу открыть его с ними! - person Euler_Salter; 01.03.2018
comment
Возможно, он сохранен в старом формате MATLAB, в этом случае вам, вероятно, следует использовать scipy.io.loadmat() docs.scipy.org/doc/scipy/reference/generated/ Это решение для формата MATLAB v.7.3 и выше. - person norok2; 28.06.2018
comment
Это работает, просто исходная матрица была размером 100x256x256x3, а результат был размером 3x256x256x100. В конце концов, мне пришлось использовать «свопакси». - person Ruchir; 25.07.2019

Я создал небольшую библиотеку для загрузки файлов MATLAB 7.3:

pip install mat73

Чтобы загрузить .mat 7.3 в Python в качестве словаря:

import mat73
data_dict = mat73.loadmat('data.mat')

просто как тот!

person skjerns    schedule 17.12.2019
comment
**** Лучший ответ прямо здесь. Большое спасибо. Такого рода работы устраняют ненужный беспорядок в работе. - person your_boy_gorja; 07.06.2020
comment
Вы герой, сэр! - person Aleksejs Fomins; 05.10.2020
comment
@Integrate. Не стесняйтесь открывать вопрос на странице github.com/skjerns/mat7.3/issues если вы думаете, что это ошибка. Под капотом mat73 полагается на h5py и скорость вашего жесткого диска. - person skjerns; 13.11.2020
comment
Почему это не входит в стандартные библиотеки? - person ThatNewGuy; 01.04.2021
comment
@ThatNewGuy ты имеешь в виду scipy? Поскольку он вводит зависимость от h5py, который не является частью стандартного lib / scipy-stack - person skjerns; 03.04.2021
comment
@skjerns извиняюсь, это была ленивая лексика с моей стороны. Я просто имею в виду общепринятые библиотеки, которые включены в ваши общие менеджеры пакетов (например, Anaconda). По соображениям безопасности моя работа не позволяет использовать какие-либо сторонние пакеты, еще не включенные в Anaconda, поэтому нет чистого способа передачи данных между Matlab и python. - person ThatNewGuy; 03.04.2021
comment
pip на самом деле является наиболее часто используемым менеджером пакетов. Если ваша работа не позволяет устанавливать какие-либо пакеты, кроме пакетов по умолчанию в Anaconda, примите мои соболезнования. Вы можете попытаться установить его в свою пользовательскую папку pip install mat73 -u или просто загрузите файл .py в свой проект и импортируйте его, это должно полностью сработать. Ваша компания никак не может помешать вам в этом. В противном случае обсудите это со своим руководителем. - person skjerns; 04.04.2021
comment
@skjerns да, если это единственный файл из Интернета, который в основном является текстовым файлом, я уверен, что все будет хорошо. Но ни о каких репозиториях не может быть и речи. Спасибо за предложение! - person ThatNewGuy; 04.04.2021

Согласно ответу Magu_ в связанной теме, ознакомьтесь с пакетом hdf5storage, который имеет удобные функции для чтения файлов matlab v7.3; это так просто, как

import hdf5storage
mat = hdf5storage.loadmat('test.mat')
person Maxim    schedule 04.11.2017
comment
Очень медленно / вылетел терминал - person s2t2; 19.07.2019
comment
это не сработает, это не будет правильно загружать типы MATLAB (cell, struct) - person skjerns; 17.12.2019

Я изучал эту проблему: https://github.com/h5py/h5py/issues/726. Если вы сохранили свой файл mat с параметром -v7.3, вы должны сгенерировать список ключей с помощью (в Python 3.x):

import h5py
with h5py.File('test.mat', 'r') as file:
    print(list(file.keys()))

Например, чтобы получить доступ к переменной a, вы должны использовать тот же трюк:

with h5py.File('test.mat', 'r') as file:
    a = list(file['a'])
person Léonard    schedule 21.09.2017

Согласно кулинарной книге Scipy. http://wiki.scipy.org/Cookbook/Reading_mat_files,

Начиная с версии 7.3 Matlab, файлы mat фактически сохраняются с использованием формата HDF5 по умолчанию (кроме случаев, когда вы используете флаг -vX во время сохранения, см. Справку по сохранению в Matlab). Эти файлы можно прочитать в Python, например, с помощью пакета PyTables или h5py. Считывание структур Matlab в файлах mat на данный момент не поддерживается.

Возможно, вы могли бы использовать Octave для повторного сохранения с помощью флага -vX.

person lee    schedule 17.06.2015
comment
Насколько я могу судить, octave также не поддерживает файлы v7.3. Так что на самом деле вам нужно будет повторно сохранить, используя достаточно свежую версию Matlab. - person Michael Anderson; 13.09.2017

Несмотря на часы поиска, я также не нашел, как получить доступ к структурам Matlab v7.3. Надеюсь, этот частичный ответ кому-то поможет, и я был бы очень рад увидеть дополнительные указатели.

Итак, начнем с (я думаю, что [0] [0] возникает из Matlab, предоставляющего все измерениям):

f = h5py.File('filename', 'r')
f['varname'][0][0]

дает: ‹Ссылка на объект HDF5>

Передайте эту ссылку снова в f:

f[f['varname'][0][0]]

который дает массив: преобразуйте его в массив numpy и извлеките значение (или, рекурсивно, другую ссылку на объект ‹HDF5>:

np.array(f[f['varname'][0][0]])[0][0]

Если доступ к диску медленный, возможно, поможет загрузка в память.


Дальнейшее редактирование: после долгих бесполезных поисков мой последний обходной путь (я действительно надеюсь, что у кого-то есть лучшее решение!) Вызывал Matlab из python, что довольно просто и быстро:

eng = matlab.engine.start_matlab()  # first fire up a Matlab instance
eng.quit()
eng = matlab.engine.connect_matlab()  # or connect to an existing one
eng.sqrt(4.0)
x = 4.0
eng.workspace['y'] = x
a = eng.eval('sqrt(y)')
print(a)
x = eng.eval('parameterised_function_in_Matlab(1, 1)', nargout=1)
a = eng.eval('Structured_variable{1}{2}.object_name')  # (nested cell, cell, object)
person Stephen Morrell    schedule 13.02.2019
comment
Я создал для вас библиотеку: github.com/skjerns/mat7.3 - person skjerns; 17.12.2019

Эта функция читает созданные Matlab файлы HDF5 .mat и возвращает структуру вложенных dicts массивов Numpy. Matlab записывает матрицы в порядке Fortran, поэтому это также переносит матрицы и многомерные массивы в обычный порядок Numpy arr[..., page, row, col].

import h5py

def read_matlab(filename):
    def conv(path=''):
        p = path or '/'
        paths[p] = ret = {}
        for k, v in f[p].items():
            if type(v).__name__ == 'Group':
                ret[k] = conv(f'{path}/{k}')  # Nested struct
                continue
            v = v[()]  # It's a Numpy array now
            if v.dtype == 'object':
                # HDF5ObjectReferences are converted into a list of actual pointers
                ret[k] = [r and paths.get(f[r].name, f[r].name) for r in v.flat]
            else:
                # Matrices and other numeric arrays
                ret[k] = v if v.ndim < 2 else v.swapaxes(-1, -2)
        return ret

    paths = {}
    with h5py.File(filename, 'r') as f:
        return conv()
person L. Kärkkäinen    schedule 20.09.2019
comment
Немного сложно отследить, но умно. - person ThatNewGuy; 03.04.2021

Если вы читаете только базовые массивы и структуры, см. ответ vikrantt на аналогичный post. Однако, если вы работаете с Matlab table, то, IMHO, лучшее решение - вообще избегать опции save.

Я создал простую вспомогательную функцию для преобразования Matlab table в стандартный файл hdf5 и другую вспомогательную функцию в Python для извлечения данных в Pandas DataFrame.

Вспомогательная функция Matlab

function table_to_hdf5(T, path, group)
%TABLE_TO_HDF5 Save a Matlab table in an hdf5 file format
%
%    TABLE_TO_HDF5(T) Saves the table T to the HDF5 file inputname.h5 at the root ('/')
%    group, where inputname is the name of the input argument for T
%
%    TABLE_TO_HDF5(T, path) Saves the table T to the HDF5 file specified by path at the
%    root ('/') group.
%
%    TABLE_TO_HDF5(T, path, group) Saves the table T to the HDF5 file specified by path
%    at the group specified by group.
%
%%%

if nargin < 2
    path = [inputname(1),'.h5'];  % default file name to input argument
end
if nargin < 3
    group = '';  % We will prepend '/' later, so this is effectively root
end

for field = T.Properties.VariableNames
    % Prepare to write
    field = field{:};
    dataset_name = [group '/' field];
    data = T.(field);
    if ischar(data) || isstring(data)
        warning('String columns not supported. Skipping...')
        continue
    end
    % Write the data
    h5create(path, dataset_name, size(data))
    h5write(path, dataset_name, data)
end

end

Вспомогательная функция Python

import pandas as pd
import h5py


def h5_to_df(path, group = '/'):
"""
Load an hdf5 file into a pandas DataFrame
"""
    df = pd.DataFrame()
    with h5py.File(path, 'r') as f:
        data = f[group]
        for k,v in data.items():
            if v.shape[0] > 1:  # Multiple column field
                for i in range(v.shape[0]):
                    k_new = f'{k}_{i}'
                    df[k_new] = v[i]
            else:
                df[k] = v[0]
    return df

Важные заметки

  • Это будет работать только с числовыми данными. Если вы знаете, как добавлять строковые данные, прокомментируйте.
  • Это создаст файл, если он еще не существует.
  • Это приведет к сбою, если данные уже существуют в файле. Вы захотите включить логику для обработки этих случаев, как вы сочтете нужным.
person ThatNewGuy    schedule 03.04.2021