2013-02-24 63 views
0

在numpy數組中使用元組時,我發現了一個奇怪的行爲。我想得到一張布爾值表,告訴我陣列a中的哪些元組也存在於數組b中。通常,我會使用in,in1d中的任何一個。他們都沒有工作,而tuple(a[1]) == b[1,1]收益率TrueNumpy:如何檢查在ndarray中存在的元組

我填補我ab這樣的:

a = numpy.array([(0,0)(1,1)(2,2)], dtype=tuple) 

b = numpy.zeros((3,3), dtype=tuple) 
for i in range(0,3): 
    for j in range(0,3): 
     b[i,j] = (i,j) 

誰能告訴我解決我的問題,請賜教爲什麼預期這不起作用?

(使用python2.7和numpy1.6.2在這裏順便說一句。)

+0

這幾乎是:http://stackoverflow.com/questions/14766194/testing-whether-a-numpy-array-contains-a-given-行/ 14772313我想你可能會在那裏找到答案。 – seberg 2013-02-24 23:31:40

回答

1

爲什麼這不起作用

短的版本是,numpy的的實施array.__contains__()似乎被打破。 Python中的in運算符在幕後調用__contains__()

含義a in b相當於b.__contains__(a)

我在一個REPL裝載了您的陣列和嘗試以下操作:

>>> b[:,0] 
array([(0, 0), (1, 0), (2, 0)], dtype=object) 
>>> (0,0) in b[:,0] # we expect it to be true 
False 
>>> (0,0) in list(b[:,0]) # this shouldn't be different from the above but it is 
True 
>>> 

如何修復

我怎麼沒看到你的列表理解可以工作,因爲a[x]是一個元組和b[:,:]是一個二維矩陣,所以它們當然不相等。但我假設你打算使用in而不是==。如果我在這裏錯了,那麼請糾正我,你的意思是我看不到的東西。

的第一步是b從二維數組轉換成一維數組,所以我們可以通過它直線篩,並將其轉換爲一個列表,以避免numpy的殘破array.__contains()像這樣:

bb = list(b.reshape(b.size)) 

或者,更好然而,使它成爲一個set因爲元組是不可變的和一組檢查in是O(1)而不是列表的O(n)的行爲

>>> bb = set(b.reshape(b.size)) 
>>> print bb 
set([(0, 1), (1, 2), (0, 0), (2, 1), (1, 1), (2, 0), (2, 2), (1, 0), (0, 2)]) 
>>> 

接下來,我們簡單地使用列表理解導出表布爾的

>>> truth_table = [tuple(aa) in bb for aa in a] 
>>> print truth_table 
[True, True, True] 
>>> 

全碼:

def contained(a,b): 
    bb = set(b.flatten()) 
    return [tuple(aa) in bb for aa in a] 
+0

很高興知道它的破壞是事實。我最終使用了或多或少的這個答案提供的'Full Code'示例。萬分感謝!還有一個問題:爲什麼你選擇'重塑'而不是'平坦'? – 2013-02-25 00:17:28

+0

因爲我只用了很少的numpy,這是我通過'help(numpy)搜索到的第一個東西。陣列)':P我不確定破碎是否是事實,但看起來確實如此,特別是在seberg對您的問題發表評論時。我會修改使用'flatten'的答案。 – entropy 2013-02-25 00:19:26

+0

甚至另一個問題:爲什麼'x,y = zip(* a)'和's = set(zip(x,y))'工作,而通常列表是可變的,因此不能直接轉換成集? – 2013-02-25 01:32:43