numpy

时间:2016-10-04 20:18:26

标签: python numpy scipy

我正在使用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数据中提取的嵌套字段的数量相比只是微不足道。

1 个答案:

答案 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_dataheader_datatrailer_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,)`数组。我没有把注意力集中在这些细节上。