2017-03-28 11 views
2

2次元が整数の3要素の部分配列である2次元配列のPython Numpy配列を持っています。Numpyの動的条件に基づいたサブアレイの値を置き換えます。

[ [1, 0, 0], [0, 0, 1], ... [0, 1, 0] ] 

この:例えば:私は、上記の例からの所望の出力は次のようになります0と1で最低数とすべての他の番号を交換したい各サブアレイに対して

[ [2, 3, 4], [9, 8, 7], ... [15, 14, 16] ] 

大きな配列なので、Numpyのパフォーマンスを利用したい。私は配列要素を操作するための条件を使用することについて知っていますが、条件が動的である場合はどうすればよいですか?この場合、条件は次のようにする必要があります。

newarray = (a == min(a)).astype(int) 

しかし、どのように各サブアレイでこれを行うのですか?

答えて

1

あなたはa == a.minbyrowを行う際に、そして、あなたは各サブアレイの最小位置にtruesを取得します(結果のディメンションを続ければ)の2D配列を計算するaxisパラメータを指定することができます。

(a == a.min(1, keepdims=True)).astype(int) 
#array([[1, 0, 0], 
#  [0, 0, 1], 
#  [0, 1, 0]]) 
+0

感謝 - これは素晴らしい作品。 –

1

これはいかがですか?

import numpy as np 

a = np.random.random((4,3)) 

i = np.argmin(a, axis=-1) 
out = np.zeros(a.shape, int) 
out[np.arange(out.shape[0]), i] = 1 

print(a) 
print(out) 

出力例:

# [[ 0.58321885 0.18757452 0.92700724] 
# [ 0.58082897 0.12929637 0.96686648] 
# [ 0.26037634 0.55997658 0.29486454] 
# [ 0.60398426 0.72253012 0.22812904]] 
# [[0 1 0] 
# [0 1 0] 
# [1 0 0] 
# [0 0 1]] 

わずかに速く直接的なアプローチよりもあるように思われる:

from timeit import timeit 

def dense(): 
    return (a == a.min(1, keepdims=True)).astype(int) 

def sparse(): 
    i = np.argmin(a, axis=-1) 
    out = np.zeros(a.shape, int) 
    out[np.arange(out.shape[0]), i] = 1 
    return out 

for shp in ((4,3), (10000,3), (100,10), (100000,1000)): 
    a = np.random.random(shp) 
    d = timeit(dense, number=40)/40 
    s = timeit(sparse, number=40)/40 
    print('shape, dense, sparse, ratio', '({:6d},{:6d}) {:9.6g} {:9.6g} {:9.6g}'.format(*shp, d, s, d/s)) 

サンプル実行:

# shape, dense, sparse, ratio ( 4,  3) 4.22172e-06 3.1274e-06 1.34992 
# shape, dense, sparse, ratio (10000,  3) 0.000332396 0.000245348 1.35479 
# shape, dense, sparse, ratio ( 100, 10) 9.8944e-06 5.63165e-06 1.75693 
# shape, dense, sparse, ratio (100000, 1000) 0.344177 0.189913 1.81229 
+0

多くの感謝 - これは良い答えです。ナンシーは確かに面白い獣です。あなたのソリューションは機能します。 –