这与我的上一个问题有关,可以找到here。我处理类似于我在该链接中描述的列表的列表作为markerList - 所以列表有三个级别。我需要将此信息保存为.mat文件,但我无法将其保存为正确的类型。当使用scipy.io.savemat时,它将列表保存为200x40x2单,当它应该是一组200个单元格,每个单元格包含一个40x2单元格。
我用来保存它的代码是:
matdict = dict(markers = (markerList), sorted = (finalStack))
scipy.io.savemat('C:\pathname\\sortedMarkers.mat', matdict)
让我感到困惑的是,它以正确的格式保存markerList(1x200单元,每个单元格大小不同),但不是finalStack(保存为200 x 40 x 2单)。最重要的是,在我弄清楚其余代码之前,它会正确地保存finalStack - 这让我觉得,当它保存的数据大小不均匀时,它可能会保存为单元格。 (finalStack的大小是统一的; markerList不是。)
有没有办法将像这样复杂的数据结构保存为.mat文件?
答案 0 :(得分:3)
根据savemat documentation,转换为'对象'的numpy数组:
from scipy.io import savemat
import numpy
a = numpy.array([[1,2,3],[1,2,3]])
b = numpy.array([[2,3,4],[2,3,4]])
c = numpy.array([[3,4,5],[3,4,5]])
L = [a,b,c]
FrameStack = numpy.empty((len(L),), dtype=numpy.object)
for i in range(len(L)):
FrameStack[i] = L[i]
savemat("myfile.mat", {"FrameStack":FrameStack})
八度音阶:
>> load myfile.mat
>> whos FrameStack
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
FrameStack 1x3 144 cell
Total is 3 elements using 144 bytes
>> whos FrameStack{1}
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
FrameStack{1} 2x3 48 int64
Total is 6 elements using 48 bytes
答案 1 :(得分:1)
如果不再查看上一个问题,我怀疑现在问题是numpy.array
从子列表或数组列表中创建数组。
您注意到markerList
已按预期保存,且单元格大小不一。
尝试
np.array(markerList)
并查看其形状和dtype。我猜测它将是1d(200,)和对象dtype。
np.array(finalStack)
另一方面,可能是它保存的3d数组。
savemat
被设置为保存numpy数组,而不是python词典和列表 - 之后,所有人都在谈论MATLAB,其中所有东西都是二维矩阵。 MATLAB单元概括了这一点;它们更像是dd对象的2d numpy数组。
经常出现从大小一致的元素创建对象数组的问题。通常的解决方案是创建所需大小的empty
数组(例如(200,))和对象类型,并将子数组加载到其中。
https://stackoverflow.com/a/38776674/901925
=============
我将演示。制作3个数组,2个一个大小,不同的第三个:
In [59]: from scipy import io
In [60]: A=np.ones((40,2))
In [61]: B=np.ones((40,2))
In [62]: C=np.ones((30,2))
保存两个列表,一个只有两个数组,另一个包含所有三个:
In [63]: io.savemat('test.mat', {'AB':[A,B],'ABC':[A,B,C]})
加载它;我可以在octave
中执行此操作:
In [65]: D=io.loadmat('test.mat')
In [66]: D.keys()
Out[66]: dict_keys(['ABC', '__header__', 'AB', '__globals__', '__version__'])
ABC
是一个包含3个元素的二维数组
In [68]: D['ABC'].shape
Out[68]: (1, 3)
In [71]: D['ABC'][0,0].shape
Out[71]: (40, 2)
但AB
已转换为3d数组:
In [69]: D['AB'].shape
Out[69]: (2, 40, 2)
In [70]: np.array([A,B]).shape
Out[70]: (2, 40, 2)
如果我改为创建一个1d对象数组来保存A和B,它将被保留:
In [72]: AB=np.empty((2,),object)
In [73]: AB[...]=[A,B]
In [74]: AB.shape
Out[74]: (2,)
In [75]: io.savemat('test.mat', {'AB':AB,'ABC':[A,B,C]})
In [76]: D=io.loadmat('test.mat')
In [77]: D['AB'].shape
Out[77]: (1, 2)
In [78]: D['AB'][0,0].shape
Out[78]: (40, 2)
一个很好的选择是将数组保存为字典的项目
io.savemat('test.mat',{'A':A, 'B':B, 'C':C})
鉴于将MATLAB结构转换为numpy结构并将其转化为困难,最好保持平坦和简单,而不是创建对双方都有用的复合对象。
===============
我安装了Octave
。加载此test.mat
:
io.savemat('test.mat', {'AB':AB,'ABs':[A,B]})
给出
>> whos
Variables in the current scope:
Attr Name Size Bytes Class
==== ==== ==== ===== =====
AB 1x2 1280 cell
ABs 2x40x2 1280 double
将对象dtype数组保存为matlab单元格;其他数组作为matlab矩阵。 (我必须回顾一下前面的答案,回忆一下matlab结构的等价物。)