2012-11-23 60 views
3

我有一個2D numpy的陣列的所有組合如下:numpy的得到的行索引和列索引2D陣列

import numpy as np 
foo = np.array([[(i+1)*(j+1) for i in range(10)] for j in range(5)]) 

    #array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
    #  [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20], 
    #  [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30], 
    #  [ 4, 8, 12, 16, 20, 24, 28, 32, 36, 40], 
    #  [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]) 

我使用創造一些過濾標準np.nonzero:

csum = np.sum(foo,axis=0) 
#array([ 15, 30, 45, 60, 75, 90, 105, 120, 135, 150]) 
rsum = np.sum(foo,axis=1) 
#array([ 55, 110, 165, 220, 275]) 
cfilter = np.nonzero(csum > 80) 
#(array([5, 6, 7, 8, 9]),) 
rfilter = np.nonzero(rsum < 165) 
#(array([0, 1]),) 

現在是有一些優雅numpy的切片方法獲取FOO [R,C]爲R的所有組合在CFILTER器Rfilter和c?即我想要得到以下的輸出:

array([[ 6, 7, 8, 9, 10], 
     [12, 14, 16, 18, 20]]) 

注:我知道這是很容易做到的基本層面選擇來從陣列,但在更高級的使用情況CFILTER和器Rfilter指數AREN塊不一定緊挨着對方。

非常感謝!

回答

1

另一種方法是使用索引兩次:

In [167]: foo[rsum<165][:,csum>80] 
Out[167]: 
array([[ 6, 7, 8, 9, 10], 
     [12, 14, 16, 18, 20]]) 

它是可讀的,並且相當快:

In [168]: %timeit foo[rsum<165][:,csum>80] 
100000 loops, best of 3: 9.66 us per loop 

In [170]: %timeit foo[np.ix_(rsum<165, csum>80)] 
100000 loops, best of 3: 16.4 us per loop 

PS:創建foo一個更快的方式是

In [31]: np.multiply.outer(range(1,6),range(1,11)) 
Out[31]: 
array([[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 
     [ 2, 4, 6, 8, 10, 12, 14, 16, 18, 20], 
     [ 3, 6, 9, 12, 15, 18, 21, 24, 27, 30], 
     [ 4, 8, 12, 16, 20, 24, 28, 32, 36, 40], 
     [ 5, 10, 15, 20, 25, 30, 35, 40, 45, 50]]) 

In [32]: %timeit np.multiply.outer(range(1,6),range(1,11)) 
100000 loops, best of 3: 14.2 us per loop 

In [33]: %timeit np.array([[(i+1)*(j+1) for i in range(10)] for j in range(5)]) 
10000 loops, best of 3: 26.6 us per loop 
+0

答案選擇,因爲它有一個更快的速度!謝謝 – ejang

5

索引叉積,使用np.ix_

foo[np.ix_(*(rfilter + cfilter))] 

您可以直接使用布爾索引(即不使用np.nonzero):

foo[np.ix_(np.sum(foo, axis=1) < 165, np.sum(foo, axis=0) > 80)] 

注意,所有np.ix_做適當添加軸以給索引數組,可以廣播一起:

>>> np.ix_(*(rfilter + cfilter)) 
(array([[0], 
     [1]]), array([[5, 6, 7, 8, 9]])) 
0

你實際上並不需要非零這一點。像(csum> 80)這樣的表達式產生一個新的矩陣。你需要的是(CSUM> 80)& &(率R sum < 165),但& &未在矩陣定義。然而,*是,它在布爾矩陣上也是這樣。你唯一的問題是你的csum和rsum數組不是正確的形狀。但是如果你正確地堆疊它們,它們可以被廣播。

csum = np.hstack (sum (foo, axis=0)) 
rsum = np.vstack (sum (foo, axis=1)) 
print foo[(csum > 80) * (hsum < 165)] 

唯一的缺點是,這會產生您在一維數組中請求的單元格的值。您需要重新塑形()以獲取您要求的格式。