Python:匹配 2 个不同长度数组并在较大数组中查找索引的有效方法

Python: efficient way to match 2 different length arrays and find index in larger array

我有 2 个数组:xbigx。它们跨越相同的范围,但 bigx 有更多的点。 例如

x = np.linspace(0,10,100)
bigx = np.linspace(0,10,1000)

我想在 bigx 中找到索引,其中 xbigx 匹配 2 个有效数字。我需要非常快地执行此操作,因为我需要积分的每个步骤的索引。

使用numpy.where很慢:

index_bigx = [np.where(np.around(bigx,2) == i) for i in np.around(x,2)]

使用 numpy.in1d 大约快 30 倍

index_bigx = np.where(np.in1d(np.around(bigx), np.around(x,2) == True)

我也尝试过使用 zipenumerate,因为我知道这应该更快,但它 returns 是空的:

>>> index_bigx = [i for i,(v,myv) in enumerate(zip(np.around(bigx,2), np.around(x,2))) if myv == v]
>>> print index_bigx
[]

我想我一定是把这里弄糊涂了,我想尽可能地优化它。有什么建议么?

如果您只需要元素,这应该可行:

np.intersect1d(np.around(bigx,2), np.around(x,2))

如果你想要索引,试试这个:

around_x = set(np.around(x,2))
index_bigx = [i for i,b in enumerate(np.around(bigx,2)) if b in around_x]

注意:这些未经测试。

由于 bigx 始终均匀分布,直接计算索引非常简单:

start = bigx[0]
step = bigx[1] - bigx[0]
indices = ((x - start)/step).round().astype(int)

线性时间,无需搜索。

由于我们将 x 映射到元素等距的 bigx,您可以使用 np.searchsorted 的分箱操作来模拟使用其 [=15= 的索引查找操作] 选项。这是实现 -

out = np.searchsorted(np.around(bigx,2), np.around(x,2),side='left')

运行时测试

In [879]: import numpy as np
     ...: 
     ...: xlen = 10000
     ...: bigxlen = 70000
     ...: bigx = 100*np.linspace(0,1,bigxlen)
     ...: x = bigx[np.random.permutation(bigxlen)[:xlen]]
     ...: 

In [880]: %timeit np.where(np.in1d(np.around(bigx,2), np.around(x,2)))
     ...: %timeit np.searchsorted(np.around(bigx,2), np.around(x,2),side='left')
     ...: 
100 loops, best of 3: 4.1 ms per loop
1000 loops, best of 3: 1.81 ms per loop