3

私は次のように2Dnumpy配列を持っています:

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]),)

rfilterのrとcfilterのcのfoo[r、c]のすべての組み合わせを取得するための、洗練されたnumpyスライシングメソッドはありますか?つまり、次の出力を取得したい:

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

注:配列からブロックを取得するために基本的なスライス選択を行うのは簡単ですが、より高度なユースケースでは、cfilterとrfilterのインデックスが必ずしも隣り合っているとは限りません。

どうもありがとう!

4

3 に答える 3

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]]))
于 2012-11-23T17:55:47.820 に答える
1

さらに別の方法は、インデックス作成を2回使用することです。

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
于 2012-11-23T19:28:24.650 に答える
0

これには、実際にはゼロ以外の値は必要ありません。(csum> 80)のような式は、新しい行列になります。必要なのは(csum> 80)&&(rsum <165)ですが、&&は行列で定義されていません。ただし、*はそうであり、ブール行列でも同じことを行います。あなたが持っている唯一の問題はあなたのcsumとrsum配列が正しい形ではないということです。ただし、正しくスタックすればブロードキャストできます。

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

唯一の欠点は、これにより、要求したセルの値が1次元配列で生成されることです。要求した形式を取得するには、reshape()する必要があります。

于 2012-11-23T18:11:09.547 に答える