godfreap godfreap - 1 year ago 158
Python Question

Using scipy.io.savemat to Save Nested Lists

This is relating to my last question, which can be found here. I'm dealing with lists similar to the list I describe in that link as markerList - so a list with three levels. I need to save this information as a .mat file, but I can't get it to save in the right type. When using scipy.io.savemat, it saves the list as a 200x40x2 single, when it should be a set of 200 cells, each containing a 40x2 cell.

The code I'm using to save this is:

matdict = dict(markers = (markerList), sorted = (finalStack))
scipy.io.savemat('C:\pathname\\sortedMarkers.mat', matdict)

What is confusing to me is that it saves markerList in the correct format (1x200 cell, each a cell of varying size), but not finalStack (saved as a 200 x 40 x 2 single). On top of that, before I had figured out the rest of this code, it would save finalStack correctly - which makes me think that perhaps it saves as a cell when the data it is saving isn't uniform in size. (finalStack is uniform in size; markerList is not.)

Is there a way to save a complicated data structure like this as a .mat file?

Answer Source

As per savemat documentation, convert into a numpy array of 'objects':

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})

In octave:

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