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

6
我是一位新手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)

我不确定如何将这个字符串数组转换成Python列表或元组,使它看起来像这样:
list_of_strings = ['thank',  'you', 'very', 'much'];

我不熟悉Python或numpy的数组对象。非常感谢您的帮助。

2个回答

5

你试过这个吗:

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']

2
b.tolist()会返回[[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')]],看起来仍然是一个数组。 - Causality
@Denzel。你必须使用 chars_as_strings=1,matlab_compatible=1 吗? - Marcin

2
这看起来是使用列表推导的工作。重复你的例子,我在MATLAB中做了这个:
cell_of_strings = {'thank',  'you', 'very', 'much'};
save('my.mat', 'cell_of_strings','-v7'); 

我正在使用更新版本的MATLAB,默认情况下将.mat文件保存为HDF5格式。 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)的数组,其中包含'thank'这个单词的字母。也就是说,
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 in array_of_strings for letter in letter_array]。 - kli_nlpr

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