2015-12-15 63 views
2

我想寫一些代碼,使用邏輯numpy數組索引較大的數組,類似於MATLAB允許數組索引邏輯數組。在numpy拋出異常邏輯索引

import numpy as np 
m = 4 
n = 4 
unCov = np.random.randint(10, size = (m,n)) 
rowCov = np.zeros(m, dtype = bool) 
colCov = np.ones(n, dtype = bool) 
>>> unCov[rowCov, rowCov] 
[] # as expected 
>>> unCov[colCov, colCov] 
[0 8 3 3] # diagonal values of unCov, as expected 
>>> unCov[rowCov, colCov] 
ValueError: shape mismatch: objects cannot be broadcast to a single shape 

對於這最後的評估,我期待一個空數組,類似於MATLAB返回的結果。我寧願不必在索引之前檢查rowCov/colCov True元素。爲什麼會發生這種情況,有沒有更好的方法來做到這一點?

+2

嗯... matlab在後一種情況下返回全矩陣,而不是對角線值。這不正確嗎? –

+0

@Andras哦,好點,你是對的!對不起,我沒有專注於MATLAB比較的那個方面。我猜numpy和MATLAB比我在這方面意識到的更加不同。 – gariepy

+1

看看這個[類似的問題](http://stackoverflow.com/questions/22357622/logical-indexing-in-numpy-with-two-indices-as-in-matlab/22366062#22366062)我認爲它回答你的問題。 –

回答

5

據我瞭解,numpy的將您的2D邏輯指數轉化爲實際的指數向量:arr[[True,False],[False,True]]將成爲arr[0,1]的形狀(2,2)ndarray。然而,在你的最後一種情況下,第二索引數組已滿False,因此它對應於長度爲0的索引陣列這與其它全True索引向量配對,對應於長度爲4

的索引陣列從the numpy manual

如果索引陣列不具有相同的形狀,有企圖 他們廣播相同的形狀。如果它們不能被廣播到 相同的形狀,將引發一個異常:

在你的情況下,錯誤也正是由於這一點:

--------------------------------------------------------------------------- 
IndexError        Traceback (most recent call last) 
<ipython-input-1411-28e41e233472> in <module>() 
----> 1 unCov[colCov,rowCov] 

IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (4,) (0,) 

MATLAB,而另一方面,自動返回如果索引數組沿着任何給定維度是空的,則爲空數組。


這實際上突出了MATLAB和numpy邏輯索引之間的根本區別。在MATLAB中,下標索引中的向量總是切出一個子陣列。也就是說,兩個

arr([1,2],[1,2]) 

arr([true,true],[true,true]) 

將返回矩陣arr2 x 2子矩陣。如果邏輯索引向量比數組的給定維度短,則缺失的索引元素被假定爲false。趣味事實:索引向量也可以是比給定的維數更長的,只要多餘的元素都是false即可。因此上述也相當於

arr([true,true,false,false],[true,true]) 

arr([true,true,false,false,false,false,false],[true,true]) 

用於4 x 4數組(參數的緣故)。

然而,在numpy中,以這種方式使用布爾值numpy arrays索引將嘗試提取一個向量。此外,布爾索引向量應該與它們索引的維度具有相同的長度。在你4 x 4例如,

unCov[np.array([True,True]),np.array([True,True])] 

unCov[np.array([True,True,False,False,False]),np.array([True,True,False,False,False])] 

都返回兩個第一對角線元素,所以不是一個小矩陣,而是一個載體。此外,他們也給沿着

/usr/bin/ipython:1: VisibleDeprecationWarning: boolean index did not match indexed array along dimension 0; dimension is 4 but corresponding boolean dimension is 5 

線路少,當時鼓勵預警所以,在numpy的,你的邏輯索引的載體應該是相同的長度ndarray的相應尺寸。然後我上面寫的是正確的:邏輯值被翻譯成索引,並且結果預期是一個向量。這個向量的長度是每個索引向量中的True元素的數量,所以如果你的布爾索引向量具有不同數量的True元素,那麼引用沒有意義,並且會得到你得到的錯誤。

+1

我基本上會寫這個。 +1。 – rayryeng

+0

我很欣賞這個解釋...非常好的信息!如果其中一個數組全部爲False,那麼在沒有首先檢查的情況下,您無法像unCov [rowCov,colCov]一樣執行常規索引,這似乎略顯非Pythonic。遊民。 – gariepy