使用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]的[微不足道]的知识会很好。
答案 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.loadmat
将onsets.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)
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]])