2013-05-02 7 views
63

私はdistsという距離の配列を持っています。私は2つの値の間にあるdistを選択したい。私はそれを行うには、次のコード行を書いた:Numpyここで関数の複数の条件

dists[(np.where(dists >= r)) and (np.where(dists <= r + dr))] 

私はそれが正常に動作し、一時変数を使用して順次コマンドを実行する場合ただし、これは条件

(np.where(dists <= r + dr)) 

のためにのみ選択します。なぜ上記のコードはうまくいかず、どうやって動作させるのですか?

乾杯

答えて

107

あなたの特定のケースではただ一つの基準にあなたの2つの基準を変更することです最善の方法:

dists[abs(dists - r - dr/2.) <= dr/2.] 

それは唯一のブール配列を作成し、私の意見では簡単です「drまたはrの中にdistと表示されていますrを最初の部分ではなく、あなたの関心領域の中心に再定義しますが、r = r + dr/2.)しかし、あなたの質問には答えません。


あなたの質問への答え:

dists[(dists >= r) & (dists <= r+dr)] 
:あなたは自分の基準に適合しないdistsの要素をフィルタリングしようとしている場合は、実際にwhereを必要としない

&は要素ごとにandとなります(括弧が必要です)。

それとも、あなたには、いくつかの理由でwhereを使いたいならば、あなたが行うことができます:

dists[(np.where((dists >= r) & (dists <= r + dr)))] 

理由:np.whereはリストを返すので、それが動作しない理由がある
ブール値の配列ではなく、インデックスの値。数字の2つのリストの間にandを取得しようとしていますが、当然True/Falseという値はありません。 abが両方ともTrueの値の場合、a and bbを返します。だから[0,1,2] and [2,3,4]のようなものは、あなたに[2,3,4]を与えるだけです。

In [239]: np.where((dists >= r) & (dists <= r + dr)) 
Out[239]: (array([10, 11, 12]),) 

In [240]: dists[np.where((dists >= r) & (dists <= r + dr))] 
Out[240]: array([ 5. , 5.5, 6. ]) 
:例今

In [236]: dists >= r 
Out[236]: 
array([False, False, False, False, False, False, False, False, False, 
     False, True, True, True, True, True, True, True, True, 
     True, True], dtype=bool) 

In [237]: dists <= r + dr 
Out[237]: 
array([ True, True, True, True, True, True, True, True, True, 
     True, True, True, True, False, False, False, False, False, 
     False, False], dtype=bool) 

In [238]: (dists >= r) & (dists <= r + dr) 
Out[238]: 
array([False, False, False, False, False, False, False, False, False, 
     False, True, True, True, False, False, False, False, False, 
     False, False], dtype=bool) 

あなたが組み合わせブールアレイ上np.whereを呼び出すことができるため、

In [230]: dists = np.arange(0,10,.5) 
In [231]: r = 5 
In [232]: dr = 1 

In [233]: np.where(dists >= r) 
Out[233]: (array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19]),) 

In [234]: np.where(dists <= r+dr) 
Out[234]: (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),) 

In [235]: np.where(dists >= r) and np.where(dists <= r+dr) 
Out[235]: (array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]),) 

何を比較するのに期待していたことは、単にブール配列した:ここではアクションであります

またはブール値配列を使用して元の配列にインデックスを付けるだけです。fancy indexing

In [241]: dists[(dists >= r) & (dists <= r + dr)] 
Out[241]: array([ 5. , 5.5, 6. ]) 
0

私は

import numpy as np 

ar = np.array([3,4,5,14,2,4,3,7]) 

print [X for X in list(ar) if (X >= 3 and X <= 6)] 

>>> 
[3, 4, 5, 4, 3] 
+5

この場合、反復する必要はありません。 NumPyにはブールインデックスがあります。 – M456

2

がしようと、この単純な例を出してきました:受け入れ答えは非常によく問題を説明しているので

np.intersect1d(np.where(dists >= r)[0],np.where(dists <= r + dr)[0]) 
16

。あなたはまた、複数の条件のために、ここで、より適しているnumpy logical functionsを使用することができます。

np.where(np.logical_and(np.greater_equal(dists,r),np.greater_equal(dists,r + dr))) 
+2

このIMOは最も読みやすい答えです! –

+1

右端には ')'がありませんか? – Olivia

+1

@Oliviaありがとうございます。) – Kasramvd

0

私は、このようなタスクのためnp.vectorizeを使用したいです。次のことを考えてみましょう:

>>> # function which returns True when constraints are satisfied. 
>>> func = lambda d: d >= r and d<= (r+dr) 
>>> 
>>> # Apply constraints element-wise to the dists array. 
>>> result = np.vectorize(func)(dists) 
>>> 
>>> result = np.where(result) # Get output. 

また、明確な出力のためにnp.argwhereの代わりnp.whereを使用することができます。しかし、あなたの呼び出しです:)

希望に役立ちます。