2016-10-04 135 views
0

我正在解析Python中的Matlab結構化數組。爲了簡單起見,數據結構最終由3個字段組成,比如標題,正文,預告片。在Matlab中創建一些數據,例如:numpy嵌套結構化數組字段訪問

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的1維numpy.ndarraydtype=dtype([('header', 'O'), ('body', 'O'), ('trailer', 'O')]),我可以愉快地遍歷使用numpy.nditer並提取和分析數據從每個結構。

我試圖克服的問題是,不幸的是(在我的控制之外)在一些我需要解析的文件中,上面定義的結構數組本身是另一個結構數組的成員,其字段爲msg。與我在Matlab示例繼續:當該在Python裝有scipy.loadmat

messages = struct('msg', {data(1), data(2), data(3)}); 

,它導致尺寸3的1維numpy.ndarraydtype=dtype([('msg', 'O')])。爲了重用相同的函數來解析數據字段,我需要邏輯來檢測msg字段(如果存在),然後在調用函數解析單個標題,正文和預告片之前從中提取每個numpy.void領域。

在Matlab中,這是很容易克服,因爲帶有三個字段的原始1×3結構陣列可以從1×3結構陣列與單msg字段通過執行來提取:[messages.msg],這產生一個1×3結構陣列與標題,正文和拖車領域。如果我試圖將其翻譯爲numpy,下面的命令會給我一個原始的numpy.ndarray的視圖,它不是一個結構(dtype=dtype('O'))。

我試圖找出是否存在與numpy類似的方式來恢復具有單個msg字段的三個字段的結構數組,如我可以在Matlab中做的,或者如果我真的需要迭代每個值並在使用常用解析函數之前從msg字段中手動提取它。再次,Matlab輸入文件的格式超出了我的控制範圍,我無法更改它們;和我需要從Matlab數據中提取的嵌套字段的數量相比,這裏的示例只是微不足道的。

回答

1

試圖重新您的文件與倍頻(保存-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是八度的細胞,這在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是結構化陣列(1,3)具有3個字段;

In [198]: data['data']['header'][0,0][0,0] 
Out[198]: 100.0 

messages是(1,3)與1場,以進一步嵌套與data。(這可能是你描述的重複,但我只想清楚一下數據結構)。

================

播放周圍,我發現,我可以剝離出(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相同。

出於某種原因,我必須在concatenate做我想要的之前將它縮減爲(3,)`數組。我還沒有將這些細節包括在內。

+0

它看起來像會工作。我嘗試用'squeeze_me = True'加載Matlab數據,因爲我能夠使用'[()]'提取值,這似乎比'[0,0]'更加微不足道,因爲它們不再存儲爲1x1數組,但這一切都讓我感到滿意。 – TWReever