2013-06-27 60 views
6

我試圖用最初在MATLAB中的numpy來重寫一個函數。還有這是一個合乎邏輯的索引部在MATLAB如下:在Numpy中通過邏輯索引獲取矩陣的網格

X = reshape(1:16, 4, 4).'; 
idx = [true, false, false, true]; 
X(idx, idx) 

ans = 

    1  4 
    13 16 

當我嘗試使它在numpy的,我不能得到正確的索引:

X = np.arange(1, 17).reshape(4, 4) 
idx = [True, False, False, True] 
X[idx, idx] 
# Output: array([6, 1, 1, 6]) 

什麼是獲得的正確方法通過邏輯索引從矩陣中得到一個網格?

+0

我聲明,我可以通過'X做[IDX,:] [:, IDX]',但不是很奇怪嗎? – petrichor

回答

7

你也可以這樣寫:

>>> X[np.ix_(idx,idx)] 
array([[ 1, 4], 
     [13, 16]]) 
+0

+1的正確索引;不知道'np.ix_'。但是,這種方法比「常規索引」的性能差(2倍)。 – root

+1

@root:這與您的方法不同,因爲它允許修改切片矩陣,而您的版本只允許只讀訪問:http://wiki.scipy.org/NumPy_for_Matlab_Users#head-13d7391dd7e2c57d293809cff080260b46d8e664 – Amro

+0

確實如此。您可能想要將其添加到您的答案中。 – root

2

numpy這叫做fancy indexing。要獲得您想要的物品,您應該使用2D指數數組。

您可以使用outer從您的1D idx合適的2D指數組成。 The outers,當應用於兩個1D序列時,將一個序列的每個元素與另一個序列的每個元素進行比較。回顧True*True=TrueFalse*True=Falsenp.multiply.outer(),這是一樣的np.outer(),可以給你2D指數:

idx_2D = np.outer(idx,idx) 
#array([[ True, False, False, True], 
#  [False, False, False, False], 
#  [False, False, False, False], 
#  [ True, False, False, True]], dtype=bool) 

,您可以使用:

x[ idx_2D ] 
array([ 1, 4, 13, 16]) 

在你真正的代碼,你可以使用x=[np.outer(idx,idx)]但它不會節省內存,工作原理與在切片後包含del idx_2D一樣。

+2

您不通過將該中間數組分配給變量來保存任何內存:它將被創建,使用並丟棄。就像在編制索引之後編寫了'del idx_2D'一樣。 – Jaime

+0

感謝您的評論,我會更新答案! –

4
In [1]: X = np.arange(1, 17).reshape(4, 4) 

In [2]: idx = np.array([True, False, False, True]) # note that here idx has to 
                # be an array (not a list) 
                # or boolean values will be 
                # interpreted as integers 

In [3]: X[idx][:,idx] 
Out[3]: 
array([[ 1, 4], 
     [13, 16]]) 
+0

+1我不知道將''dx'列表轉換爲數組將允許使用'x [idx]' –