2012-11-23 149 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)] 

唯一的缺点是,这会产生您在一维数组中请求的单元格的值。您需要重新塑形()以获取您要求的格式。