在 python 中读取 v 7.3 mat 文件
Posted
技术标签:
【中文标题】在 python 中读取 v 7.3 mat 文件【英文标题】:reading v 7.3 mat file in python 【发布时间】:2013-06-23 09:41:36 【问题描述】:我正在尝试使用以下代码读取 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
任何人都可以遇到同样的问题,并且可以请任何示例代码
谢谢
【问题讨论】:
相关:***.com/q/874461/1714410 【参考方案1】:尝试使用h5py
模块
import h5py
with h5py.File('test.mat', 'r') as f:
f.keys()
【讨论】:
是的,但是有一个结构数组,我不知道如何阅读它,f.keys()
应该为您提供存储在'test.mat'
中的变量的名称。你能访问f['s'][0].keys()
吗?假设s
是您存储的结构数组的名称,这应该会为您提供s
的字段列表。
不,我无法访问它,更具体地说,我正在尝试读取以下网站 ufldl.stanford.edu/housenumbers 中给出的 mat 文件,在文件 train.tar.gz 中,有一个名为digitStruct.mat
这个答案并没有真正提供足够的背景来实际以这种方式使用 mat 文件。当然可以打开文件,但是使用scipy.io.loadmat
,文件以透明的数据结构(即字典和numpy数组)表示。如果它还指出了如何实际访问 HDF 数据结构,那么答案将得到显着改善。
这段代码会给你一本字典。通过提取与键关联的数据,即变量名,我们可以得到类似数组的数据结构。例如<HDF5 dataset "fv": shape (18000, 9475), type "<f4">
。可以直接从此数据结构中访问行或列,或者我们可以通过np.array(data_structure)
轻松将其转换为numpy数组。【参考方案2】:
我创建了一个small library 来加载 MATLAB 7.3 文件:
pip install mat73
要将.mat
7.3 作为字典加载到 Python 中:
import mat73
data_dict = mat73.loadmat('data.mat')
就这么简单!
【讨论】:
****最佳答案就在这里。太感谢了。这类作品消除了很多不必要的工作混乱。 你是英雄先生! 为什么这不是标准库的一部分? @ThatNewGuy 你的意思是scipy
?因为它引入了对 h5py
的依赖,这不是标准 lib/scipy-stack 的一部分
pip
实际上是最常用的包管理器。如果您的工作不允许安装除 Anaconda 中的默认软件包之外的任何软件包,我表示哀悼。您可以尝试将其安装在您的用户文件夹pip install mat73 -u
中,或者只需将 .py 文件下载到您的项目并导入它,这绝对可以。您的公司应该没有办法阻止您这样做。否则,请与您的主管讨论。【参考方案3】:
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
字典中得到你的数据,除非你有 MATLAB 结构,我怀疑。希望对您有所帮助!
【讨论】:
您发现了什么问题?你检查过 MATLAB(或 octave)可以打开文件吗? 是的,我可以用他们打开它! 可能是用旧的 MATLAB 格式保存的,在这种情况下你应该使用scipy.io.loadmat()
docs.scipy.org/doc/scipy/reference/generated/… 这个解决方案适用于 MATLAB 格式 v.7.3 及更高版本。
有效,只是原始矩阵的大小为 100x256x256x3,但结果的大小为 3x256x256x100。我最终不得不使用“swapaxes”。【参考方案4】:
根据Magu_'s answer on a related thread,查看包hdf5storage,它具有读取v7.3 matlab mat 文件的便利功能;就这么简单
import hdf5storage
mat = hdf5storage.loadmat('test.mat')
【讨论】:
非常慢/终端崩溃 这不起作用,它不会正确加载 MATLAB 类型(cell
,struct
)【参考方案5】:
我看过这个问题:https://github.com/h5py/h5py/issues/726。如果您使用-v7.3
选项保存了您的 mat 文件,您应该使用(在 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'])
【讨论】:
【参考方案6】:根据 Scipy 食谱。 http://wiki.scipy.org/Cookbook/Reading_mat_files,
从 Matlab 7.3 版本开始,mat 文件实际上默认使用 HDF5 格式保存(除非您在保存时使用 -vX 标志,请参阅 Matlab 中的保存帮助)。这些文件可以在 Python 中读取,例如,使用 PyTables 或 h5py 包。 目前似乎不支持在 mat 文件中读取 Matlab 结构。
也许您可以使用 Octave 使用 -vX 标志重新保存。
【讨论】:
据我所知,octave 也不支持 v7.3 文件。所以你真的需要使用最新的 matlab 版本重新保存。【参考方案7】:尽管搜索了几个小时,我也没有找到如何访问 Matlab v7.3 结构。希望这个部分答案会对某人有所帮助,我很高兴看到额外的指针。
所以从(我认为 [0][0] 源于 Matlab 将所有内容赋予维度)开始:
f = h5py.File('filename', 'r')
f['varname'][0][0]
给出:
再次将此引用传递给 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_variable12.object_name') # (nested cell, cell, object)
【讨论】:
我已经为你创建了一个库:github.com/skjerns/mat7.3【参考方案8】:此函数读取 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()
【讨论】:
有点难以追踪,但很聪明。 为我工作。太好了! 有没有办法返回一个数组而不是一个带有平面数据和指针的字典?如何将字典变成数组?【参考方案9】:如果您只阅读基本数组和结构,请参阅 vikrantt 的 answer 类似的 post。但是,如果您使用的是 Matlab table
,那么恕我直言,最好的解决方案是完全避免使用 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
重要提示
这仅适用于数字数据。如果您知道如何添加字符串数据,请发表评论。 如果文件不存在,这将创建该文件。 如果文件中已经存在数据,这将崩溃。您需要在您认为合适的时候加入处理这些情况的逻辑。【讨论】:
以上是关于在 python 中读取 v 7.3 mat 文件的主要内容,如果未能解决你的问题,请参考以下文章