2016-07-14 10 views
4

たとえば、0から1までの範囲の値の配列rがあります。私は中央値からある閾値であるすべての値を取り除きたい。ここで、その閾値が0.5であり、len(r) = 3000であると仮定しよう。そして、この範囲外のすべての値をマスクするために、私は私の好きなシンプルなリスト内包、行うことができます。NumPyでこのPythonリストの理解をどうやって行えますか?

mask = np.array([ri < np.median(r)-0.5 or ri > np.median(r)+0.5 for ri in r])

を、私はそれにタイマーを使用する場合:

import time 
import numpy as np 

start = time.time() 
r = np.random.random(3000) 
m = np.median(r) 
maxr,minr = m-0.5, m+0.5 
mask = [ri<minr or ri>maxr for ri in r] 
end = time.time() 
print('Took %.4f seconds'%(end-start)) 

>>> Took 0.0010 seconds

このリストの理解を迅速に行う方法はありますか?NumPyを使用してマスクを作成しますか?


編集:私は含めて、以下のいくつかの提案を試みた

  • 要素単位またはオペレータ:(r<minv) | (r>maxv)

  • A numpyの論理的か: r[np.logical_or(r<minr, r>maxr)]

  • 絶対差ブール配列:abs(m-r) > 0.5

そして、ここでは、それぞれが通過300の実行後にかかった平均時間です:あなたが見ることができるように、

Python list comprehension: 0.6511 ms 
Elementwise or: 0.0138 ms 
Numpy logical or: 0.0241 ms 
Absolute difference: 0.0248 ms 

要素ごとのか、常に最速だったが、ほぼ2倍になります(配列要素でどのようにスケーリングされるのかわかりません)。誰かわかったね。

+0

'[RI <'ここにマイナス記号タイプミスです-maxr? – ayhan

+0

@ayhan yea申し訳ありませんが、最小値と最大値が無効になりました。 – Anonymous

+1

Try '(r> maxr)| (r ayhan

答えて

3

numpyの条件付き選択を使用して、それらの値なしで新しい配列を作成できます。

start = time.time() 
m = np.median(r) 
maxr,minr = m-0.5, m+0.5 
filtered_array = r[ (r < minr) | (r > maxr) ] 
end = time.time() 
print('Took %.4f seconds'%(end-start)) 

filtered_arrayは、マスクされた値(以降既にfiltered_arrayで除去し、マスクにより除去されるすべての値)無しrのスライスです。

アップデート:@ayhanが提案する短い構文が使用されました。

+0

これは最速です。ありがとうございます。 'np.logical_or()'を使った元の答えは遅くなりました。 – Anonymous

3

ワンライナー...

new_mask = abs(np.median(r) - r) > 0.5 
+0

ニースと簡潔ですが、最速ではありません、私の編集を参照してください。 – Anonymous

+0

配布の末尾が必要なときに非常に便利です。私は明快さが好きです。 –