我正在使用Python解析Matlab结构化数组。为简单起见,数据结构最终由3个字段组成,例如标题,正文,尾部。在Matlab中创建一些数据,例如:
header_data = {100, 100, 100};
body_data = {1234, 100, 4321};
trailer_data = {1001, 1001, 1001};
data = struct('header', header_data, 'body', body_data, 'trailer', trailer_data);
产生1x3结构数组。
然后在Python中读取此数据,如下所示:
import scipy.io as sio
import numpy as np
matlab_data = sio.loadmat('data.mat', squeeze_me=True)
data = matlab['data']
这使得data
成为大小为3的numpy.ndarray
dtype=dtype([('header', 'O'), ('body', 'O'), ('trailer', 'O')])
,我可以愉快地使用numpy.nditer
进行迭代,并从每个结构中提取和解析数据
我试图克服的问题是,在我需要解析的一些文件中,遗憾的是(并且我无法控制),上面定义的struct数组本身是另一个带有字段的struct数组的成员{ {1}}。继续我在Matlab中的例子:
msg
如果在Python中加载messages = struct('msg', {data(1), data(2), data(3)});
,则会生成大小为3 scipy.loadmat
的{{1}} numpy.ndarray
。为了重用相同的函数来解析数据字段,我需要有逻辑来检测dtype=dtype([('msg', 'O')])
字段(如果存在),然后在调用之前从那里提取每个msg
。用于解析单个标题,正文和预告字段的函数。
在Matlab中,这很容易克服,因为可以通过执行:numpy.void
从具有单个msg
字段的1x3结构数组中提取具有三个字段的原始1x3结构数组,从而产生1x3结构带有标题,正文和尾部字段的数组。如果我尝试将其翻译为numpy,则以下命令会为我提供原始[messages.msg]
的视图,该视图不是结构(numpy.ndarray
)。
我试图找出与dtype=dtype('O')
类似的方法来恢复具有单个numpy
字段的三个字段的结构数组,就像我在Matlab中可以做到的那样,或者如果我真的需要迭代每个值并在使用通用解析函数之前从msg
字段手动提取它。同样,Matlab输入文件的格式不受我的控制,我无法改变它们;这里我的例子与我需要从Matlab数据中提取的嵌套字段的数量相比只是微不足道。
答案 0 :(得分:2)
尝试使用Octave重新创建文件(使用-v7保存),我得到了一个Ipython会话:
In [190]: data = io.loadmat('test.mat')
In [191]: data
Out[191]:
{'__globals__': [],
'__header__': b'MATLAB 5.0 MAT-file, written by Octave 4.0.0, 2016-10-04 20:54:53 UTC',
'__version__': '1.0',
'body_data': array([[array([[ 1234.]]), array([[ 100.]]), array([[ 4321.]])]], dtype=object),
'data': array([[([[100.0]], [[1234.0]], [[1001.0]]),
([[100.0]], [[100.0]], [[1001.0]]),
([[100.0]], [[4321.0]], [[1001.0]])]],
dtype=[('header', 'O'), ('body', 'O'), ('trailer', 'O')]),
'header_data': array([[array([[ 100.]]), array([[ 100.]]), array([[ 100.]])]], dtype=object),
'messages': array([[([[(array([[ 100.]]), array([[ 1234.]]), array([[ 1001.]]))]],),
([[(array([[ 100.]]), array([[ 100.]]), array([[ 1001.]]))]],),
([[(array([[ 100.]]), array([[ 4321.]]), array([[ 1001.]]))]],)]],
dtype=[('msg', 'O')]),
'trailer_data': array([[array([[ 1001.]]), array([[ 1001.]]), array([[ 1001.]])]], dtype=object)}
body_data
,header_data
,trailer_data
是Octave单元格,numpy
是包含2d元素的2d对象数组
In [194]: data['trailer_data'][0,0]
Out[194]: array([[ 1001.]])
In [195]: data['trailer_data'][0,0][0,0]
Out[195]: 1001.0
data
是一个带有3个字段的结构化数组(1,3);
In [198]: data['data']['header'][0,0][0,0]
Out[198]: 100.0
messages
是(1,3),包含1个字段,与data
一样进一步嵌套。
In [208]: data['messages']['msg'][0,0]['header'][0,0][0,0]
Out[208]: 100.0
(这可能是您所描述内容的重复,但我只是想清楚数据结构)。
=====
到处玩,我发现,我可以使用索引编制并连接(1,3)
msg
In [241]: np.concatenate(data['messages']['msg'][0])
Out[241]:
array([[([[100.0]], [[1234.0]], [[1001.0]])],
[([[100.0]], [[100.0]], [[1001.0]])],
[([[100.0]], [[4321.0]], [[1001.0]])]],
dtype=[('header', 'O'), ('body', 'O'), ('trailer', 'O')])
In [242]: data['data']
Out[242]:
array([[([[100.0]], [[1234.0]], [[1001.0]]),
([[100.0]], [[100.0]], [[1001.0]]),
([[100.0]], [[4321.0]], [[1001.0]])]],
dtype=[('header', 'O'), ('body', 'O'), ('trailer', 'O')])
形状:
data
这看起来与master
相同。
出于某种原因,我必须在连接执行我想要的操作之前将其缩减为(3,)`数组。我没有把注意力集中在这些细节上。