SciPy 和 MATLAB,我在重建数组以匹配使用 scipy.io.loadmat(( 加载的 MATLAB 单元数组给出的内容时遇到问题。
例如,假设我在 MATLAB 中创建了一个包含一对双数组的单元格,然后使用 scipy.io 加载它(我使用 SPM 与 pynifti 等结合使用进行成像分析(
马特实验室
>> onsets{1} = [0 30 60 90]
>> onsets{2} = [15 45 75 105]
蟒
>>> 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 来解析日志文件并构建这些起始单元格数组,因此我希望能够从头开始构建它们。
当我尝试从打印输出构建相同的数组时,我得到了不同的形状:
>>> 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 的 [微不足道] 知识会很好。
这是我个人觉得在 python 中有点烦人的事情之一。这是因为loadmat
会自动"挤压"尺寸。
默认情况下,squeeze_me=True,因此如您所见,您会得到以下内容:
>>> x = sio.loadmat('mymat.mat',squeeze_me=True)
>>> y = x['onsets']
>>> y.shape
(2,)
如果使用squeeze_me设置为 False 的负载垫,则不会挤出一个维度:
>>> a = sio.loadmat('mymat.mat',squeeze_me=False)
>>> a
>>> b = a['onsets']
>>> b.shape
(1, 2)
也就是说,我一生都无法弄清楚如何为像"onset"这样的细胞阵列显示另一个维度(即b.shape = (1,2,4)
(。我只能为非单元普通的香草 MATLAB 数组获得它
onset_array = [onsets{1}; onsets{2}];
来自scipy邮件列表的Travis回应说,构建它的正确方法是先创建结构,然后填充数组:
http://article.gmane.org/gmane.comp.python.scientific.user/31760
> 你可以用以下方法构建你以前看到的东西:>> new_onsets = 空((2,(, dtype=对象(> new_onsets[0] = 数组([[0, 30, 60, 90]](> new_onsets[1] = 数组([[15, 45, 75, 105]](
我认为这里的问题是单元格数组并不是真正的数组,这就是为什么scio.loadmat
onsets.mat
加载到object
数组的原因。
在这里,您的单元格数组可以简化为形状(2,1,4)
的正常数组,但是如果数据如下所示:
>> onsets{1} = {0 30 60 'bob'}
>> onsets{2} = {15 45 75 'fred'}
我不确定最好的解决方案是什么,但是如果您知道您的数据是一个数组,那么在保存在 Matlab 中之前或使用 Scipy 加载后,您可能应该转换为普通数组。
编辑:理论上,上面的示例单元格数组可以转换为numpy结构化数组,但请注意,单元格数组通常不是这样,因为列不必是相同的数据类型。表示任意数据类型列表的逻辑方法是使用 Python 列表(或此处的列表数组(,这就是loadmat
返回的内容。
编辑2:修复单元格数组语法,如Erik Kastman建议的那样。