如何使用 Scipy.io.loadmat 将 Matlab mat 文件中的字符串单元格数组加载到 Python 列表或元组中

Posted

技术标签:

【中文标题】如何使用 Scipy.io.loadmat 将 Matlab mat 文件中的字符串单元格数组加载到 Python 列表或元组中【英文标题】:How to load cell array of strings in Matlab mat files into Python list or tuple using Scipy.io.loadmat 【发布时间】:2011-06-16 07:13:58 【问题描述】:

我是一个 Matlab 用户,不熟悉 Python。我想将 Matlab 中的字符串单元数组写入 Mat 文件,并使用 Python(可能是 scipy.io.loadmat)将此 Mat 文件加载到一些类似的类型(例如字符串列表或字符串元组)中。但是 loadmat 将内容读入数组,我不确定如何将其转换为列表。我尝试了无法按预期工作的“tolist”函数(我对 Python 数组或 numpy 数组了解甚少)。例如:

Matlab 代码:

cell_of_strings = 'thank',  'you', 'very', 'much';
save('my.mat', 'cell_of_strings');

Python 代码:

matdata=loadmat('my.mat', chars_as_strings=1, matlab_compatible=1);
array_of_strings = matdata['cell_of_strings']

那么,变量array_of_strings就是:

array([[[[u't' u'h' u'a' u'n' u'k']], [[u'y' u'o' u'u']],
    [[u'v' u'e' u'r' u'y']], [[u'm' u'u' u'c' u'h']]]], dtype=object)

我不知道如何将此 array_of_strings 转换为 Python 列表或元组,使其看起来像

list_of_strings = ['thank',  'you', 'very', 'much'];

我不熟悉 Python 或 numpy 中的数组对象。您的帮助将不胜感激。

【问题讨论】:

【参考方案1】:

你试过了吗:

import scipy.io as si

a = si.loadmat('my.mat')
b = a['cell_of_strings']                # type(b) <type 'numpy.ndarray'>
list_of_strings  = b.tolist()           # type(list_of_strings ) <type 'list'>

print list_of_strings 
# output: [u'thank', u'you', u'very', u'much']

【讨论】:

b.tolist() 给出 [[array([[u't', u'h', u'a', u'n', u'k']], dtype=' @Denzel。是否必须使用 chars_as_strings=1, matlab_compatible=1?【参考方案2】:

这看起来像是list comprehension 的工作。重复你的例子,我在 MATLAB 中做了这个:

cell_of_strings = 'thank',  'you', 'very', 'much';
save('my.mat', 'cell_of_strings','-v7'); 

我使用的是较新版本的 MATLAB,它默认以 HDF5 格式保存 .mat 文件。 loadmat 无法读取 HDF5 文件,所以 '-v7' 标志是强制 MATLAB 保存到旧版本的 .mat 文件,loadmat 可以理解。

在 Python 中,我像您一样加载了元胞数组:

import scipy.io as sio
matdata = sio.loadmat('%s/my.mat' %path, chars_as_strings=1, matlab_compatible=1);  
array_of_strings = matdata['cell_of_strings']

打印array_of_strings 给出:

[[array([[u't', u'h', u'a', u'n', u'k']], 
          dtype='<U1')
      array([[u'y', u'o', u'u']], 
          dtype='<U1')
      array([[u'v', u'e', u'r', u'y']], 
          dtype='<U1')
      array([[u'm', u'u', u'c', u'h']], 
          dtype='<U1')]]

变量array_of_strings 是一个 (1,4) numpy 对象数组,但每个对象中都嵌套了数组。例如,array_of_strings 的第一个元素是一个 (1,5) 数组,其中包含表示“谢谢”的字母。也就是说,

array_of_strings[0,0]
array([[u't', u'h', u'a', u'n', u'k']], 
      dtype='<U1')

要获得第一个字母“t”,您必须执行以下操作:

array_of_strings[0,0][0,0]
u't'

由于我们正在处理嵌套数组,我们需要使用一些递归技术来提取数据,即嵌套for 循环。但首先,我将向您展示如何提取第一个单词:

first_word = [str(''.join(letter)) for letter in array_of_strings[0][0]]
first_word
['thank']

我在这里使用列表推导。基本上,我正在遍历 array_of_strings[0][0] 中的每个字母,并使用''.join 方法将它们连接起来。 string() 函数是将 unicode 字符串转换为常规字符串。

现在,为了得到你想要的列表字符串,我们只需要遍历每个字母数组:

words = [str(''.join(letter)) for letter_array in array_of_strings[0] for letter in letter_array]
words
['thank', 'you', 'very', 'much']

列表推导式需要一些时间来适应,但它们非常有用。希望这会有所帮助。

【讨论】:

words = [str(''.join(letter)) for letter_array in array_of_strings[0] for letter in letter_array] 应该是 words = [str(''.join(letter)) for letter_array在 array_of_strings 中为 letter_array 中的字母]

以上是关于如何使用 Scipy.io.loadmat 将 Matlab mat 文件中的字符串单元格数组加载到 Python 列表或元组中的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Scipy.io.loadmat 将 Matlab mat 文件中的字符串单元格数组加载到 Python 列表或元组中

使用 scipy.io loadmat 将 Matlab 结构导入 python 时的值错误

从使用 Scipy.io.loadmat 加载的 .mat 文件访问数组内容 - python

使用 scipy.io.loadmat 从 .mat Matlab 文件中将字典键转换为 Python 中具有相同值的变量名

Scipy IO Loadmat 错误:ValueError:Mat 4 mopt 格式错误

SciPy中两个模块:io 和misc