2013-10-23 32 views
11

我有一個整數數組,並且希望找到該數組等於多個值列表中的任何值的位置。這可以通過單獨處理每個值或通過在循環中使用多個「或」語句來輕鬆完成,但我覺得必須有更好/更快的方式來完成。我在實際處理規模4000x2000的陣列,但這裏是一個問題的簡化版:找到一個numpy數組等於值列表中的任何值

fake=arange(9).reshape((3,3)) 
array([[0, 1, 2], 
     [3, 4, 5], 
     [6, 7, 8]]) 
want=(fake==0)+(fake==2)+(fake==6)+(fake==8) 
print want 
array([[ True, False, True], 
     [False, False, False], 
     [ True, False, True]], dtype=bool) 

我想是一種方法,從一個單一的命令涉及fake和值[0,2,6,8]的名單得到want 。我可以自己編寫命令,但是我假設有一個包含這個包的包,比我在python中用循環編寫函數的速度要快得多。

感謝, - 亞當

回答

14

功能numpy.in1d似乎做你想要什麼。唯一的問題是,它僅適用於一維數組,所以你應該使用這樣的:

In [9]: np.in1d(fake, [0,2,6,8]).reshape(fake.shape) 
Out[9]: 
array([[ True, False, True], 
     [False, False, False], 
     [ True, False, True]], dtype=bool) 

我不知道爲什麼,這是僅限於一維數組。看看它的source code,它似乎首先使兩個陣列變平,然後它做了一些巧妙的排序技巧。但是,沒有什麼能夠阻止它在最後解除結果,就像我必須在這裏手工完成一樣。

+0

嗯。我寫了這個非常簡單的功能做這個工作: \t'高清EqualsAny(AR,丘壑): \t OUT =零(ar.shape,D型=布爾) \t爲VAL瓦爾斯: \t OUT + =(AR == VAL) \t回out' 我認爲'numpy.in1d'會更快,但它實際上需要更長的時間(對於相同的結果): \t'[11]:%timeit EqualsAny(badlabels,smallnum ) \t 1循環,最好3:每循環519 ms \t In [7]:%timeit in1d(badlabels,smallnum).reshape(badla bels.shape) \t 1循環,最好是3:每循環871毫秒' 不應該''numpy.in1d'以更快的速度寫入C?我沒有正確使用'%timeit'嗎? – arwright3

+0

不,'in1d'不是用c寫的,而是用python編寫的,請參閱我給出的源代碼的鏈接。它使用了'sort'等各種numpy函數,它應該可以用C編寫。甚至當'vals'很短時,它甚至有一些優化的算法,這與你的解決方案非常相似(但使用'| ='代替' + =')。我不知道爲什麼你的版本更快,這可能取決於兩個輸入的長度。 –

5

@ Bas的答案是你可能要找的那個。但這裏的另一種方式來做到這一點,使用numpy的的vectorize招:

import numpy as np 
S = set([0,2,6,8]) 

@np.vectorize 
def contained(x): 
    return x in S 

contained(fake) 
=> array([[ True, False, True], 
      [False, False, False], 
      [ True, False, True]], dtype=bool) 

這種解決方案的con是,contained()被每件(即蟒蛇空間),這使得這麼多比純鐵慢numpy解決方案。

相關問題