Python:匹配 2 个不同长度数组并在较大数组中查找索引的有效方法
Python: efficient way to match 2 different length arrays and find index in larger array
我有 2 个数组:x
和 bigx
。它们跨越相同的范围,但 bigx
有更多的点。
例如
x = np.linspace(0,10,100)
bigx = np.linspace(0,10,1000)
我想在 bigx
中找到索引,其中 x
和 bigx
匹配 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)
我也尝试过使用 zip
和 enumerate
,因为我知道这应该更快,但它 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
我有 2 个数组:x
和 bigx
。它们跨越相同的范围,但 bigx
有更多的点。
例如
x = np.linspace(0,10,100)
bigx = np.linspace(0,10,1000)
我想在 bigx
中找到索引,其中 x
和 bigx
匹配 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)
我也尝试过使用 zip
和 enumerate
,因为我知道这应该更快,但它 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