元素索引的矢量化搜索

时间:2015-02-21 21:15:26

标签: python arrays numpy

我有两个整数numpy数组,比如,arr1arr2,它们是range(some_length)

的排列

我想得到第三个,其中

所有arr3[idx] = arr1.get_index_of(arr2[idx])

idx = 0,1,2,..., some_length-1

这里get_index_of method是获取集合中某个元素的索引的伪方法。

这可以通过对所有的indeces进行天真循环来完成,搜索对应的元素,然后分配它的索引等等。

但这很慢 - O(n ^ 2)。可以更快地完成(至少n * log(n)复杂度)?可以通过漂亮的numpy方法完成吗?也许用一些非平凡的key=参数进行排序?当然有一些优雅的解决方案。

提前谢谢。

2 个答案:

答案 0 :(得分:2)

说,a0..9排列

>>> a = np.random.permutation(10)
>>> a
array([3, 7, 1, 8, 2, 4, 6, 0, 9, 5])

然后,索引器数组是:

>>> i = np.empty(len(a), dtype='i8')
>>> i[a] = np.arange(len(a))
>>> i
array([7, 2, 4, 0, 5, 9, 6, 1, 3, 8])

这意味着,0中的a索引为i[0] == 7,自a[7] == 0起为真。

因此,在您的示例中,假设您有一个额外的向量b,您可以执行以下操作:

>>> b
array([5, 9, 4, 8, 6, 1, 7, 2, 3, 0])
>>> i[b]
array([9, 8, 5, 3, 6, 2, 1, 4, 0, 7])

这意味着,b[0] == 5 5a中的i[b][0] == 9索引为a[9] = 5 = b[0],这是真的,因为{{1}}。

答案 1 :(得分:1)

让我们试一下测试用例

In [166]: arr1=np.random.permutation(10)
In [167]: arr2=np.random.permutation(10)
In [168]: arr1
Out[168]: array([4, 3, 2, 9, 7, 8, 5, 1, 6, 0])
In [169]: arr2
Out[169]: array([9, 2, 6, 4, 0, 3, 1, 7, 8, 5])

np.where(arr1==i)会执行您的get_index_of method,因此您的迭代解决方案是:

In [170]: np.array([np.where(arr1==i)[0] for i in arr2]).flatten()
Out[170]: array([3, 2, 8, 0, 9, 1, 7, 4, 5, 6], dtype=int32)

矢量化方法是在2个数组之间进行“outter”比较。这会生成一个(10,10)数组,我们可以应用where来获取索引。仍然是O(n ^ 2)方法,但它主要是编译的。在这个问题的大小上,它快5倍。

In [171]: np.where(arr1==arr2[:,None])
Out[171]: 
(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=int32),
 array([3, 2, 8, 0, 9, 1, 7, 4, 5, 6], dtype=int32))