2012-05-10 41 views
2

使用SciPy和MATLAB,我很難重建一個數組以匹配使用scipy.io.loadmat()加載的MATLAB單元格數組中給出的數組。在numpy數組中加載了scipy.io.loadmat的ndim?

舉例來說,假設我創建包含一對在MATLAB雙陣列的細胞,然後使用scipy.io加載它(我使用SPM做成像與pynifti等結合分析)

MATLAB

>> onsets{1} = [0 30 60 90] 
>> onsets{2} = [15 45 75 105] 

的Python

>>> import scipy.io as scio 
>>> mat = scio.loadmat('onsets.mat') 
>>> mat['onsets'][0] 
array([[[ 0 30 60 90]], [[ 15 45 75 105]]], dtype=object) 

>>> mat['onsets'][0].shape 

(2,) 

我的問題是:爲什麼這個numpy的陣列具有的形狀(2),而不是(2,1,4)?在現實生活中,我試圖用Python來解析日誌文件並構建這些起始單元陣列,所以我希望能夠從頭開始構建它們。

當我嘗試從打印輸出建立相同的數組,得到了一個不同的形狀回:

>>> new_onsets = array([[[ 0, 30, 60, 90]], [[ 15, 45, 75, 105]]], dtype=object) 
array([[[0, 30, 60, 90]], 

     [[15, 45, 75, 105]]], dtype=object) 

>>> new_onsets.shape 
(2,1,4) 

不幸的是,該形狀(在單元陣列雙打的向量)在一個規範被編碼的上游,所以我需要能夠以這種格式完全保存。當然,這不是什麼大問題,因爲我可以在MATLAB中編寫解析器,但是很容易弄清楚發生了什麼,併爲我的[小] numpy知識添加一點點。

回答

1

從SciPy的郵件列表特拉維斯迴應說,建立這個正確的方法是先創建結構,然後填充陣列:

http://article.gmane.org/gmane.comp.python.scientific.user/31760

 
> You could build what you saw before with: 
> 
> new_onsets = empty((2,), dtype=object) 
> new_onsets[0] = array([[0, 30, 60, 90]]) 
> new_onsets[1] = array([[15, 45, 75, 105]]) 
+0

再次回到這裏; scipy.io現在有一個非常有用的參考資料:http://docs.scipy.org/doc/scipy/reference/tutorial/io.html –

1

這是我個人覺得在python中討厭的東西之一。這是因爲loadmat會自動「擠壓」尺寸。

默認情況下,squeeze_me = true,所以你見過你這樣的:

>>> x = sio.loadmat('mymat.mat',squeeze_me=True) 
>>> y = x['onsets'] 
>>> y.shape 
(2,) 

如果使用loadmat與squeeze_me設置爲false,那麼你沒有得到一名維擠掉:

>>> a = sio.loadmat('mymat.mat',squeeze_me=False) 
>>> a 
>>> b = a['onsets'] 
>>> b.shape 
(1, 2) 

這就是說,我不能爲我的生活弄清楚如何獲得另一個維度來顯示(即,b.shape = (1,2,4))像'onsets'這樣的單元格數組。我只能夠得到它的非細胞純老香草MATLAB陣列

onset_array = [onsets{1}; onsets{2}]; 
+0

感謝您的快速答覆!我不確定squeeze_me正在做什麼,但即使使用squeeze_me = False,我仍然會(2,)。 (也許它看起來不夠細胞陣列?)我會盡量繼續挖掘,並讓我知道,如果我找到任何東西。 (同樣,我不確定在savemat中do_compression做了什麼,但它在我的任何測試中都沒有影響。 –

+0

要正確構建尺寸,scipy列表說首先用empty()和然後用數據填充 –

+1

'討厭python'不應該是「令人討厭的** scipy **」兩個*非常*不同的東西scipy,numpy,matplotlib(注:所有*第三方外部模塊*)形式一個非常不同的世界,根據我的經驗,他們的某些部分完全忽視了pythonic哲學而不贊成他們自己,並非毫不客氣地表達更好的想法 – n611x007

1

我覺得這裏的問題是,電池陣列並不是真正的數組,這就是爲什麼scio.loadmat負載onsets.matobject陣列。

在這裏,你的電池陣列可以減少到形狀(2,1,4)的正常排列,但如果相反,你的數據看起來像:

>> onsets{1} = {0 30 60 'bob'} 
>> onsets{2} = {15 45 75 'fred'} 

我不知道最好的解決辦法是什麼,但如果你知道你的數據是一個數組,你應該在保存到Matlab之前或者在使用Scipy進行加載之前將其轉換爲普通數組。

編輯:示例單元陣列上面,在理論上,被扔在一個numpy的structured array,但要注意,因爲列不必爲相同的數據類型,這不是一般電池陣列的真實。表示任意數據類型列表的邏輯方法是使用Python列表(或這裏的一系列列表),這是loadmat返回的內容。

編輯2:修正單元陣列語法,如Erik Kastman所建議的。

+1

我同意這不是一個非常numpy兼容的格式,但這是我需要使用的對於另一個軟件包,我鎖定了它。 我認爲你需要在上面的例子中製作單元陣列,例如:{0 30 60'bob'};這將是嵌套單元陣列。有數組雙打,所以我不需要擔心子電池或結構。 –