2013-05-02 75 views
63

我有一個稱爲dists的距離數組。我想選擇介於兩個值之間的dists。我寫了下面的代碼行做到這一點:Numpy功能多個條件

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

然而,這僅選擇爲條件

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

如果我用它工作正常臨時變量做的命令順序。爲什麼上面的代碼不起作用,我如何才能使它工作?

乾杯

回答

107

你的具體情況將只是給你兩個標準更改爲一個標準的最好方法:

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

它僅創建一個布爾數組,而在我看來是比較容易閱讀,因爲它說,distdrr(雖然我會重新定義r是您感興趣的地區的中心而不是開始,所以r = r + dr/2.)但是這並不能回答你的問題。


回答你的問題:
你實際上並不需要where,如果你只是想篩選出不符合您的標準的dists元素:

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

因爲&會給你一個元素and(括號是必要的)。

或者,如果你想使用where出於某種原因,你可以這樣做:

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

爲什麼:
它不工作的原因,是因爲np.where返回一個列表的索引,而不是布爾數組。您正試圖在兩個數字列表之間獲得and,這當然沒有您期望的True/False值。如果ab都是True值,則a and b返回b。所以說像[0,1,2] and [2,3,4]只會給你[2,3,4]。這是在行動:

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

什麼您期望比較簡單地是布爾數組,例如

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 [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. ]) 

或簡單地使用布爾數組索引原始數組使用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 2013-05-02 17:12:58

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是最可讀的答案! – 2017-02-22 15:56:22

+1

最後錯過了')'但是對不對? – Olivia 2017-11-14 14:32:46

+1

@Olivia是的,謝謝提醒;) – Kasramvd 2017-11-14 15:19:25

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清晰輸出。但那是你的電話:)

希望它有幫助。