2010-02-25 182 views
9

我有兩個數組,a1和a2。假設len(a2) >> len(a1),並且a1是a2的子集。返回兩個numpy數組之間的公共元素索引

我想快速返回a1中所有元素的a2索引。這樣做的時間密集方式顯然是:

from operator import indexOf 
indices = [] 
for i in a1: 
    indices.append(indexOf(a2,i)) 

這當然需要很長時間,其中a2很大。我也可以使用numpy.where()來代替(雖然a1中的每個條目在a2中只會出現一次),但我不相信它會更快。我還可以穿越大陣只有一次:

for i in xrange(len(a2)): 
    if a2[i] in a1: 
     indices.append(i) 

但我敢肯定有一個更快,更「numpy的」的方式 - 我通過numpy的方法列表看去,卻什麼也找不到合適的。

提前許多感謝,

d

回答

8

如何

numpy.nonzero(numpy.in1d(a2, a1))[0] 

這應該是快。從我的基本測試來看,它比您的第二代碼片段len(a2) == 100,len(a1) == 10000快7倍,並且在索引45處僅有一個公共元素。這假定a1a2都沒有重複元素。

+0

我比較你的解決方案戴夫柯比的上面,這對於len(a2)==約12347424,len(a1)== 1338約爲1.35X更快,所以這個解決方案得到了我的投票 - 謝謝! – Dave 2010-02-25 11:57:37

+3

對於讀這個的人:看起來像'setmember1d'自numpy 1.4以來已被重命名爲'in1d'。 – 2012-10-16 16:26:07

+0

@AlokSinghal感謝您的支持! – 2016-06-10 18:59:45

2

怎麼樣:

wanted = set(a1) 
indices =[idx for (idx, value) in enumerate(a2) if value in wanted] 

這應該是O(LEN(A1)+ LEN(A2)),而不是O(LEN(A1 )* len(a2))

NB我不知道numpy,所以可能會有更''numpythonic'的方式來做到這一點,但這是我如何在純python中做到這一點。

+0

應該枚舉(a2)? – Dave 2010-02-25 11:55:51

+0

糟糕,我的壞。現在修復它。 – 2010-02-25 20:13:56

1
index = in1d(a2,a1) 
result = a2[index] 
0

numpy_indexed包(聲明:我是它的作者)包含一個向量化的list.index;表現應該與目前接受的答案類似,但作爲獎勵,它還可以明確控制缺失值,並使用「缺失」kwarg。

import numpy_indexed as npi 
indices = npi.indices(a2, a1, missing='raise') 

此外,它也將在多維數組,即工作,找到一組在其他行的索引。

1

與@AlokSinghal非常相似,但您獲得了一個已經變平的版本。

numpy.flatnonzero(numpy.in1d(a2, a1))