I am trying to create a Matlab file (*.mat) from Python that contains a Matlab data structure that would look like:
s.key1 where key1 is an array of values
s.key2 where key2 is an array of 1D arrays
s.key3 where key3 is an array of 2D arrays
If I use savemat and a dictionary, the Matlab output is a cell array rather than a Matlab data structure.
I have tried using
np.core.records.fromarrays(data_list, names=q_keys)
but this doesn't seem to work for keys with 2D arrays. I have both 2D and 3D arrays that need to be in a Matlab structure for compatibility with an existing file format. Is there a way to do this in Python?
Thanks
解决方案
Here's a stab at the task:
In [292]: dt = np.dtype([('key1',int),('key2',int, (3,)),('key3',object)])
In [293]: arr = np.zeros((5,), dt)
In [294]: arr
Out[294]:
array([(0, [0, 0, 0], 0), (0, [0, 0, 0], 0), (0, [0, 0, 0], 0),
(0, [0, 0, 0], 0), (0, [0, 0, 0], 0)],
dtype=[('key1', '
In [295]: arr['key1']=np.arange(5)
In [296]: arr['key2']=np.arange(15).reshape(5,3)
In [302]: arr['key3']=[1,np.arange(5),np.ones((2,3),int),'astring',[['a','b']]]
In [303]: io.savemat('test.mat', {'astruct':arr})
In Octave:
>> load test.mat
>> format compact
>> astruct
astruct =
1x5 struct array containing the fields:
key1
key2
key3
>> astruc.key1
error: 'astruc' undefined near line 1 column 1
>> astruct.key1
ans = 0
ans = 1
ans = 2
ans = 3
ans = 4
>> astruct.key2
ans =
0 1 2
ans =
3 4 5
ans =
6 7 8
ans =
9 10 11
ans =
12 13 14
>> astruct.key3
ans = 1
ans =
0 1 2 3 4
ans =
1 1 1
1 1 1
ans = astring
ans = ab
Back in ipython:
In [304]: d = io.loadmat('test.mat')
In [305]: d
Out[305]:
{'__header__': b'MATLAB 5.0 MAT-file Platform: posix, Created on: Wed Jun 6 15:36:23 2018',
'__version__': '1.0',
'__globals__': [],
'astruct': array([[(array([[0]]), array([[0, 1, 2]]), array([[1]])),
(array([[1]]), array([[3, 4, 5]]), array([[0, 1, 2, 3, 4]])),
(array([[2]]), array([[6, 7, 8]]), array([[1, 1, 1],
[1, 1, 1]])),
(array([[3]]), array([[ 9, 10, 11]]), array(['astring'], dtype='
(array([[4]]), array([[12, 13, 14]]), array([['a', 'b']], dtype='
dtype=[('key1', 'O'), ('key2', 'O'), ('key3', 'O')])}
So while a created a numpy structured array with dtypes like int and int(3), the loaded array has object dtype for all fields. loadmat makes heavy use of object dtype arrays to handle the generality of MATLAB cells and struct. loadmat has various loading parameters, which we can play with.
This was just a guess based on previous experience loading MATLAB files. If this isn't what you want, I'd suggest constructing sample data in MATLAB, save that, and then load to see how loadmat constructs it. You may have to go back and forth a few times to work out the bugs.