在numpy数组中的ndim加载了scipy.io.loadmat?

时间:2012-05-10 21:15:20

标签: python matlab numpy scipy mat-file

使用SciPy和MATLAB,我无法重建数组,以匹配使用scipy.io.loadmat()加载的MATLAB单元格数组。

例如,假设我在MATLAB中创建一个包含一对双数组的单元格,然后使用scipy.io加载它(我使用SPM与pynifti等一起进行成像分析)

MATLAB

>> onsets{1} = [0 30 60 90]
>> onsets{2} = [15 45 75 105]

的Python

>>> import scipy.io as scio
>>> mat = scio.loadmat('onsets.mat')
>>> mat['onsets'][0]
array([[[ 0 30 60 90]], [[ 15  45  75 105]]], dtype=object)

>>> mat['onsets'][0].shape

(2,)

我的问题是:为什么这个numpy数组的形状(2,)而不是(2,1,4)?在现实生活中,我正在尝试使用Python来解析日志文件并构建这些onsets单元格数组,因此我希望能够从头开始构建它们。

当我尝试从打印输出中构建相同的数组时,我得到了不同的形状:

>>> new_onsets = array([[[ 0, 30, 60, 90]], [[ 15,  45,  75, 105]]], dtype=object)
array([[[0, 30, 60, 90]],

       [[15, 45, 75, 105]]], dtype=object)

>>> new_onsets.shape
(2,1,4)

不幸的是,形状(单元格数组中的双精度矢量)是在规范上游编码的,所以我需要能够以这种格式准确地保存它。当然,因为我可以在MATLAB中编写解析器,所以这并不是什么大不了的事情,但是弄清楚发生了什么并且稍微增加了我对[numpy]的[微不足道]的知识会很好。

3 个答案:

答案 0 :(得分:1)

这是我个人觉得在python中很烦人的事情之一。这是因为loadmat会自动“挤压”尺寸。

默认情况下,squeeze_me = True,所以你看到你得到了这个:

>>> x = sio.loadmat('mymat.mat',squeeze_me=True)
>>> y = x['onsets']
>>> y.shape
(2,)

如果你使用loadmat并将squeeze_me设置为False,那么你就不会挤出一个维度:

>>> a = sio.loadmat('mymat.mat',squeeze_me=False)
>>> a
>>> b = a['onsets']
>>> b.shape
(1, 2)

那就是说,我不能为我的生活弄清楚如何为像'onsets'这样的单元格数组出另一个维度(即b.shape = (1,2,4))。我只能用非单元普通的香草MATLAB数组来获取它

onset_array = [onsets{1}; onsets{2}];

答案 1 :(得分:1)

我认为这里的问题是单元格数组不是真正的数组,这就是scio.loadmatonsets.mat加载到object数组的原因。

在这里,您的单元格数组可以缩小为正常的形状(2,1,4)数组,但是,如果您的数据看起来如下:

>> onsets{1} = {0 30 60 'bob'}
>> onsets{2} = {15 45 75 'fred'}

我不确定最佳解决方案是什么,但是如果你知道你的数据是一个数组,你应该在保存到Matlab之前或者在用Scipy加载之后转换为普通数组。

编辑:理论上,上面的示例单元格数组可以转换为numpy structured array,但请注意,对于单元格数组通常不正确,因为列不必是相同的数据类型。表示任意数据类型列表的逻辑方法是使用Python列表(或列表数组),这是loadmat返回的内容。

编辑2:按照Erik Kastman的建议修复单元格数组语法。

答案 2 :(得分:1)

来自scipy邮件列表的Travis回应说,构建它的正确方法是首先创建结构,然后填充数组:

http://article.gmane.org/gmane.comp.python.scientific.user/31760

> You could build what you saw before with: 
> 
> new_onsets = empty((2,), dtype=object) 
> new_onsets[0] = array([[0, 30, 60, 90]]) 
> new_onsets[1] = array([[15, 45, 75, 105]])