如何解决Python / Numpy-快速找到最接近某个值的数组中的索引
|| 我有一个值数组t,该值始终按升序排列(但不总是等距排列)。我还有另一个单一值x。我需要在t中找到索引,以使t [index]最接近x。对于ximport numpy as np
import timeit
t = np.arange(10,100000) # Not always uniform,but in increasing order
x = np.random.uniform(10,100000) # Some value to find within t
def f1(t,x):
ind = np.searchsorted(t,x) # Get index to preserve order
ind = min(len(t)-1,ind) # In case x > max(t)
ind = max(1,ind) # In case x < min(t)
if x < (t[ind-1] + t[ind]) / 2.0: # Closer to the smaller number
ind = ind-1
return ind
def f2(t,x):
return np.abs(t-x).argmin()
print t,\'\\n\',x,\'\\n\'
print f1(t,x),f2(t,\'\\n\'
print t[f1(t,x)],t[f2(t,\'\\n\'
runs = 1000
time = timeit.Timer(\'f1(t,x)\',\'from __main__ import f1,t,x\')
print round(time.timeit(runs),6)
time = timeit.Timer(\'f2(t,\'from __main__ import f2,6)
解决方法
这似乎要快得多(对我来说,Python 3.2-win32,numpy 1.6.0):
from bisect import bisect_left
def f3(t,x):
i = bisect_left(t,x)
if t[i] - x > 0.5:
i-=1
return i
输出:
[ 10 11 12 ...,99997 99998 99999]
37854.22200356027
37844
37844
37844
37854
37854
37854
f1 0.332725
f2 1.387974
f3 0.085864
,“ 3”是二进制搜索(每次将数组分成两半)。因此,您必须以返回小于x的最后一个值而不是返回零的方式来实现它。
查看此算法(从此处开始):
def binary_search(a,x):
lo=0
hi = len(a)
while lo < hi:
mid = (lo+hi)//2
midval = a[mid]
if midval < x:
lo = mid+1
elif midval > x:
hi = mid
else:
return mid
return lo-1 if lo > 0 else 0
只是替换了最后一行(是return -1
)。还更改了参数。
由于循环是用Python编写的,因此它可能比第一个慢...(未进行基准测试)
,使用搜索排序:
t = np.arange(10,100000) # Not always uniform,but in increasing order
x = np.random.uniform(10,100000)
print t.searchsorted(x)
编辑:
嗯,是的,我知道这就是您在f1中所做的。也许下面的f3比f1更容易阅读。
def f3(t,x):
ind = t.searchsorted(x)
if ind == len(t):
return ind - 1 # x > max(t)
elif ind == 0:
return 0
before = ind-1
if x-t[before] < t[ind]-x:
ind -= 1
return ind
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。