matlab 在python中读取v7.3 mat文件

smdncfj3  于 2022-11-15  发布在  Matlab
关注(0)|答案(9)|浏览(239)

我正在尝试使用以下代码读取一个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

那么,有没有人能遇到同样的问题,并且可以取悦任何示例代码
谢谢

kqlmhetl

kqlmhetl1#

我已经创建了一个small library来加载MatLab 7.3文件:

pip install mat73

要将.mat 7.3作为词典加载到Python中,请执行以下操作:

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

就这么简单!

xxls0lw8

xxls0lw82#

尝试使用h5py模块

import h5py
with h5py.File('test.mat', 'r') as f:
    f.keys()
svdrlsy4

svdrlsy43#

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)

我怀疑,除非您有matlab结构,否则您最终应该得到arrays字典中的数据。希望它能帮上忙!

voase2hg

voase2hg4#

根据Magu_'s answer on a related thread,查看hdf5storage包,它具有读取v7.3 MatLab MAT文件的方便函数;它非常简单,如下所示

import hdf5storage
mat = hdf5storage.loadmat('test.mat')
hzbexzde

hzbexzde5#

我看过这个问题:https://github.com/h5py/h5py/issues/726。如果您使用-v7.3选项保存MAT文件,则应该使用(在Python3.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'])
enyaitl3

enyaitl36#

根据Scipy的食谱。http://wiki.scipy.org/Cookbook/Reading_mat_files
从MatLab 7.3版开始,MAT文件实际上默认使用HDF5格式保存(除非在保存时使用-vx标志,请参见帮助保存在MatLab中)。例如,可以使用PyTables或h5py包在Python中读取这些文件。目前似乎不支持读取MAT文件中的MatLab结构。
也许您可以使用Octave来使用-vx标志重新保存。

toiithl6

toiithl67#

尽管搜索了几个小时,我也没有找到如何访问MatLab v7.3结构。希望这个部分的答案会对某些人有所帮助,我很高兴看到更多的指点。
所以从(我认为[0][0]产生于MatLab将一切都赋予维度)开始:

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

给出:<HDF5对象引用>
再次将此引用传递给f:

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

它给出了一个数组:将其转换为NumPy数组并提取值(或者递归地提取另一个:

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

如果访问磁盘的速度很慢,加载到内存可能会有所帮助。
进一步编辑:在搜索了我的最终解决方案后(我真的希望其他人有更好的解决方案!)我是从Python调用MatLab的,这非常容易和快速:

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)
a11xaf1n

a11xaf1n8#

此函数用于读取由Matlab生成的HDF5.mat文件,并返回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()
w80xi6nr

w80xi6nr9#

如果您只读入基本的数组和结构,请参阅vikrantt的answer在类似的post上。但是,如果您使用的是MatLab table,那么最好的解决方案是完全避免使用save选项。
我已经创建了一个简单的助手函数来将MatLab table转换为标准的hdf5文件,并创建了另一个助手函数来将数据提取到Pandas DataFrame中。

Matlab Helper函数

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 Helper函数

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

重要说明

  • 这将仅对数字数据起作用。如果你知道如何添加字符串数据,请评论。
  • 如果文件尚不存在,此操作将创建该文件。
  • 如果数据已存在于文件中,则会崩溃。您需要包含逻辑,以便在您认为合适的时候处理这些情况。

相关问题