在Python中读取.mat文件

567

在Python中能否读取二进制MATLAB .mat文件?

我看到SciPy声称支持读取.mat文件,但我用它不成功。我安装了版本为0.7.0的SciPy,但找不到loadmat()方法。

16个回答

773

需要导入模块,import scipy.io...

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

32
Scipy不支持v7.3的mat文件(请参见这里的说明)。查看vikrantt的回答以获得解决方案。 - texnic
1
然而,您可以将MAT文件保存为早期版本。请参见:http://www.mathworks.com/help/matlab/import_export/mat-file-versions.html(标题:“保存为非默认MAT文件版本”) - watsonic
7
好的,我会尽力进行翻译。以下是您需要翻译的内容:
  1. What is your name?
  2. Can you translate this document for me?
  3. How much will it cost to translate this document?
  4. How long will it take to translate this document?
  5. Thank you for your help.
- watsonic
2
更新了 SciPy.io 教程的链接 https://docs.scipy.org/doc/scipy/tutorial/io.html @FranckDernoncourt - ZaydH

216

对于MATLAB数组版本7.3,既不能使用scipy.io.savemat,也不能使用scipy.io.loadmat。但好消息是,MATLAB版本7.3文件是hdf5数据集。因此可以使用许多工具来读取它们,包括NumPy

对于Python,您需要h5py扩展程序,在您的系统上需要安装HDF5。

import numpy as np
import h5py
f = h5py.File('somefile.mat','r')
data = f.get('data/variable1')
data = np.array(data) # For converting to a NumPy array

8
如果在Matlab中保存数据时使用“-v7.3”标志,这将很好地工作。使用默认的“save”(至少在Matlab R2014b中)会导致生成一个文件,无法使用上述技术进行读取。如果确实使用了“-v7.3”标志,则可以轻松读取数值数据。 - chipaudette
5
没错,这正是我在帖子中说的。在Matlab中保存时,你需要使用-v7.3。不管怎样,你应该这么做,因为它使用的格式更好/更受支持/更标准化。 - vikrantt
5
请问你能否解释一下在你的例子中,f 和 data 之间的关系是什么?我该如何将 f 移动到一个 numpy 数组中? - heracho
4
我如何知道它是否包含了 data/variable1 文件夹下的数据? - devspartan
8
f.keys()会显示您可以访问的内容。 - Packard CPW
显示剩余4条评论

33

首先将.mat文件保存为:

save('test.mat', '-v7')

然后,在Python中使用通常的loadmat函数:

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

27

有一个很好的软件包叫做 mat4py,可以很容易地使用以下方法进行安装:

pip install mat4py

这是一个易于使用的工具(来自网站):

从MAT文件中加载数据

函数loadmat将存储在MAT文件中的所有变量加载到简单的Python数据结构中,仅使用Python的dictlist对象。 数字和单元数组转换为行顺序嵌套列表。 数组被压缩以消除只有一个元素的数组。 生成的数据结构由与JSON格式兼容的简单类型组成。

示例:将MAT文件加载到Python数据结构中:

from mat4py import loadmat

data = loadmat('datafile.mat')

变量data是一个dict,其中包含在MAT文件中的变量和值。 将Python数据结构保存到MAT文件 可以使用函数savemat将Python数据保存到MAT文件中。数据必须按照与loadmat相同的方式进行结构化,即它应由简单的数据类型组成,如dictliststrintfloat
例子:将Python数据结构保存到MAT文件中:
from mat4py import savemat

savemat('datafile.mat', data)

参数data应该是一个包含变量的dict

请注意,mat4py为您提供类似JSON的字典树、列表、列表中的列表等——完全没有numpy。(mat4py/cmd.py my.mat会将my.json写成1行长的文件。) - denis
1
@denis:是的,这也在上面提到了。但确实是一个好点:我通常喜欢这种结构,例如在Web应用程序中,因为numpy数组不可JSON序列化 - Cleb
1
遇到了错误:mat4py.loadmat.ParseError: 只能读取 Matlab 5 级别的 MAT 文件 - s2t2
请注意,mat4py不允许读取复数值.mat文件。 - SjonTeflon
1
如果在Raspberry Pi上无法使用scipy,则回退的好解决方案。对于纯数字数据,速度更快,但如果有字符串则速度较慢。 - save_jeff
显示剩余5条评论

17

如果安装了MATLAB 2014b或更新版本,则可以使用Python的MATLAB引擎

import matlab.engine
eng = matlab.engine.start_matlab()
content = eng.load("example.mat", nargout=1)

我遇到了这个错误:ModuleNotFoundError: No module named 'pylab'。 - VimNing
3
你在尝试这个答案时遇到了错误?很奇怪,因为它没有使用pylab。 - Daniel
1
仅供参考,此答案需要有效的Matlab安装和许可证 - 它在后台运行Matlab以完成读取。并且可能会有限制,需要进一步处理才能使它们可读。例如,Simulink.Bus对象以“matlab对象”的形式出现,必须进一步处理,如果要提取Bus Element对象,则存在问题。 - LightCC

15

读取文件

import scipy.io
mat = scipy.io.loadmat(file_name)

检查MAT变量的类型

print(type(mat))
#OUTPUT - <class 'dict'>

词典中的MATLAB变量,而则是分配给这些变量的对象


我遇到一个错误:“ValueError: Unknown mat file type, version 9, 99”。有什么办法可以解决吗? - sam wolfe

15

有一个很好的库可以完成这个任务,叫做:pymatreader

只需要按照以下步骤操作:

  1. 安装包:pip install pymatreader

  2. 导入相关功能:from pymatreader import read_mat

  3. 使用该函数读取matlab struct:data = read_mat('matlab_struct.mat')

  4. 使用 data.keys() 定位实际存储数据的位置。

  • 键通常看起来像这样:dict_keys(['__header__', '__version__', '__globals__', 'data_opp'])。其中data_opp将是实际存储数据的关键字。当然,在不同的文件之间可以更改此键的名称。
  1. 最后一步 - 创建您的数据框:my_df = pd.DataFrame(data['data_opp'])

就是这样 :)


1
它做得更好的两件事是:它保留了 mat 对象的维度,并且加载的对象是 NumPy 数组。谢谢。 - nKandel
1
很高兴它有帮助 :) - Ofir Shorer

10

还有由MathWorks开发的MATLAB Engine for Python。如果你拥有MATLAB,这可能值得考虑(我个人没有尝试过,但它比仅仅读取MATLAB文件拥有更多的功能)。然而,我不知道是否允许将其分发给其他用户(如果那些人拥有MATLAB,则可能不是问题。否则,NumPy可能是正确的选择?)

此外,如果您想自己完成所有基础工作,MathWorks提供了一份关于文件格式结构的详细文档(如果链接失效,请尝试Google搜索“matfile_format.pdf”或其标题“MAT-FILE Format”)。这不像我个人认为的那么复杂,但显然这不是最简单的方法。这也取决于您要支持多少.mat文件的功能。

我写了一个“小”(大约700行)的Python脚本,可以读取一些基本的.mat文件。我既不是Python专家也不是初学者,用了大约两天时间来编写它(使用上面链接的MathWorks文档)。我学到了很多新东西,也很有趣(大部分时间)。由于我在工作中编写了Python脚本,所以恐怕无法发布它...但我可以在这里提供一些建议:

  • 首先阅读文档。
  • 使用十六进制编辑器(如HxD)并查看您想要解析的参考.mat文件。
  • 尝试通过将字节保存到.txt文件并注释每行来弄清楚每个字节的含义。
  • 使用类来保存每个数据元素(例如miCOMPRESSEDmiMATRIXmxDOUBLEmiINT32
  • .mat文件的结构最适合将数据元素保存在树状数据结构中,每个节点有一个类和子节点。

  • 12
    这是MathWorks提供的一份有点疯狂的文档。它解释了40页的格式,但没有提到它是HDF5的子集。 - Daniel
    它不再存在了。 - Mour_Ka
    1
    @Mour_Ka,链接的PDF文件我仍然可以打开。 - mozzbozz
    抱歉,我指的是Python的Matlab引擎。如果我没记错的话,这是新链接:https://de.mathworks.com/help/matlab/matlab-engine-for-python.html。 - Mour_Ka

    10

    将mat文件读取为带有混合数据类型的pandas数据框

    import scipy.io as sio
    mat=sio.loadmat('file.mat')# load mat-file
    mdata = mat['myVar']  # variable in mat file 
    ndata = {n: mdata[n][0,0] for n in mdata.dtype.names}
    Columns = [n for n, v in ndata.items() if v.size == 1]
    d=dict((c, ndata[c][0]) for c in Columns)
    df=pd.DataFrame.from_dict(d)
    display(df)
    

    5
    除了对于v4(Level 1.0)、v6、v7到7.2 mat文件使用的scipy.io.loadmat和针对7.3格式mat文件使用的h5py.File外,在文本数据格式下有另一种类型的mat文件,通常是由Octave创建的,这些mat文件甚至无法在MATLAB中读取。无论是scipy.io.loadmat还是h5py.File都不能加载它们(已针对scipy 1.5.3和h5py 3.1.0进行测试),我找到的唯一解决方案是numpy.loadtxt
    import numpy as np
    mat = np.loadtxt('xxx.mat')
    

    1
    至少对于使用MATLAB生成的.mat文件,这将导致UnicodeDecodeError - emilaz
    1
    @emilaz 这是可以预料的。np.loadtxt 只适用于由 Octave 生成的 .mat 文件。 - MrCrHaM
    1
    是的,我只是把它放在那里作为未来查看此内容的人的澄清。 - emilaz

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接