2010-06-12 136 views
80

假設我有一個numpy數組x = [5, 2, 3, 1, 4, 5]y = ['f', 'o', 'o', 'b', 'a', 'r']。我想選擇在y對應於x元素的元素大於1且小於5numpy數組,如何選擇滿足多個條件的索引?

我試圖

x = array([5, 2, 3, 1, 4, 5]) 
y = array(['f','o','o','b','a','r']) 
output = y[x > 1 & x < 5] # desired output is ['o','o','a'] 

但這不起作用。我將如何做到這一點?

回答

134

你表達作品,如果你加括號:

>>> y[(1 < x) & (x < 5)] 
array(['o', 'o', 'a'], 
     dtype='|S1') 
+0

這很好.. vecMask = 1 Ralf 2016-11-03 17:08:18

+1

omg這太奇怪了 – 2017-05-27 16:54:19

+0

@JennyYueJin:這是因爲優先。 (按位)'&'具有比'<' and '>'更高的優先級,其優先級高於(邏輯)'和'。 x> 1和x <5'先不等式,然後邏輯連接; 'x> 1&x <5'計算'1'和('in)'x'中的位的連接點,然後是不等式。 (x> 1)&(x <5)'迫使不平等先評估,所有的操作都按照預定的順序進行,結果都是明確的。 [請參閱文檔](https://docs.python.org/3/reference/expressions.html#operator-precedence) – calavicci 2017-11-16 17:58:41

23

IMO OP實際上並不希望np.bitwise_and() (aka &)但實際上想要np.logical_and()因爲它們比較如TrueFalse邏輯值 - 看到這個SO張貼在logical vs. bitwise看區別。

>>> x = array([5, 2, 3, 1, 4, 5]) 
>>> y = array(['f','o','o','b','a','r']) 
>>> output = y[np.logical_and(x > 1, x < 5)] # desired output is ['o','o','a'] 
>>> output 
array(['o', 'o', 'a'], 
     dtype='|S1') 

和等價的方式來做到這一點是np.all()通過適當設置axis說法。

>>> output = y[np.all([x > 1, x < 5], axis=0)] # desired output is ['o','o','a'] 
>>> output 
array(['o', 'o', 'a'], 
     dtype='|S1') 

由數字:

>>> %timeit (a < b) & (b < c) 
The slowest run took 32.97 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 1.15 µs per loop 

>>> %timeit np.logical_and(a < b, b < c) 
The slowest run took 32.59 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000000 loops, best of 3: 1.17 µs per loop 

>>> %timeit np.all([a < b, b < c], 0) 
The slowest run took 67.47 times longer than the fastest. This could mean that an intermediate result is being cached. 
100000 loops, best of 3: 5.06 µs per loop 

所以使用np.all()是比較慢,但是&logical_and大約相同。

+7

你需要小心一點,你如何談論評估的內容。例如,在'output = y [np.logical_and(x> 1,x <5)]'中,* x * *被評估(可能創建一個巨大的數組),即使它是第二個參數,因爲評估發生在函數之外。 IOW,'logical_and'獲得兩個已經評估過的參數。這與'a和b'的常見情況不同,其中如果'a'是真實的,則不評估'b'。 – DSM 2013-09-05 19:29:43

+12

布爾數組的bitwise_and()和logical_and()之間沒有區別 – jfs 2014-04-13 20:07:12

14

向@ J.F添加一個細節。塞巴斯蒂安和@馬克Mikofski的答案:
如果想獲得相應的指標(而不是數組的實際值),下面的代碼將做到:

爲了滿足多個(所有)條件:

select_indices = np.where(np.logical_and(x > 1, x < 5)) # 1 < x <5 

爲了滿足多個(或)條件:

select_indices = np.where(np.logical_or(x < 1, x > 5)) # x <1 or x >5 
+0

請注意,numpy.where不僅會返回索引數組,而且會返回包含數組的元組(包括condition.nonzero()的輸出) - 在這種情況下,'(你想要的索引數組),'所以你需要'select_indices = np.where(...)[0]'來得到你想要的結果。 – calavicci 2017-11-16 18:11:20

1

其實我會做這種方式:

L1是滿足條件1的元素的索引列表;(可以使用somelist.index(condition1)np.where(condition1)來獲得L1)。

然後你找到使用intersect(L1,L2)的路口。

如果您滿足多個條件,您還可以找到多個列表的交集。

然後,您可以將索引應用於任何其他數組,例如x。

1

我喜歡用np.vectorize來完成這樣的任務。考慮以下內容:

>>> # Arrays 
>>> x = np.array([5, 2, 3, 1, 4, 5]) 
>>> y = np.array(['f','o','o','b','a','r']) 

>>> # Function containing the constraints 
>>> func = np.vectorize(lambda t: t>1 and t<5) 

>>> # Call function on x 
>>> y[func(x)] 
>>> array(['o', 'o', 'a'], dtype='<U1') 

優點是您可以在矢量化函數中添加更多類型的約束。

希望它有幫助。

相關問題