查找最接近的值并返回Python中的数组索引
我发现这篇文章: Python:在数组中find一个元素
它是通过匹配值来返回一个数组的索引。
另一方面,我所做的是相似但不同的。 我想find目标值的最接近的值。 例如我正在寻找4.2,但我知道在数组中没有4.2,但我想要返回值4.1的索引而不是4.4。
什么是最快的方式呢?
我正在考虑像以前那样用Matlab来做这个事情,它使用数组A,我想从索引中减去目标值,然后取绝对值,然后select最小值。 像这样的东西: –
[~,idx] = min(abs(A - target))
这是Matlab的代码,但我是Python的新手,所以我想,是否有一种快速的方式在Python?
非常感谢你的帮助!
这与使用bisect_left类似,但它可以让你传入一个目标数组
def find_closest(A, target): #A must be sorted idx = A.searchsorted(target) idx = np.clip(idx, 1, len(A)-1) left = A[idx-1] right = A[idx] idx -= target - left < right - target return idx
一些解释:
首先是一般情况: idx = A.searchsorted(target)为每个target返回一个索引,使得target位于A[index - 1]和A[index] 。 我把这些left调用,所以我们知道left < target <= right 。 target - left < right - target为True (或1),当目标更接近left时为False (或0),当目标更接近right 。
现在特例:当target小于A所有元素时, idx = 0 。 idx = np.clip(idx, 1, len(A)-1)将idx <1的所有值replace为1,所以idx=1 。 在这种情况下, left = A[0] , right = A[1] ,我们知道target <= left <= right 。 因此,我们知道target - left <= 0和right - target >= 0因此target - left < right - target为True除非target == left == right和idx - True = 0 。
如果target大于A所有元素,则还有另外一种特殊情况,在这种情况下, idx = A.searchsorted(target)和np.clip(idx, 1, len(A)-1)将len(A)replace为len(A) - 1所以idx=len(A) -1和target - left < right - target结束False所以idx返回len(A) -1 。 我会让你通过自己的逻辑工作。
例如:
In [163]: A = np.arange(0, 20.) In [164]: target = np.array([-2, 100., 2., 2.4, 2.5, 2.6]) In [165]: find_closest(A, target) Out[165]: array([ 0, 19, 2, 2, 3, 3])
除了使用numpy.argmin来查找最小索引之外,相应的Numpy代码几乎是一样的。
idx = numpy.argmin(numpy.abs(A - target))
testing和定时两个解决scheme:
idx = np.searchsorted(sw, sCut)
和
idx = np.argmin(np.abs(sw - sCut))
用于计算时间昂贵的方法。 第二种解决scheme的计算时间为113 秒 , 第一种计算的时间为132s 。
那么,超过2年过去了,我发现从这个URL实际上很简单的实现: 在numpy数组中find最接近的值
实施是:
def getnearpos(array,value): idx = (np.abs(array-value)).argmin() return idx
干杯!!
可能的scheme
>>> a = [1.0, 3.2, -2.5, -3.1] >>> i = -1.5 >>> diff = [(abs(i - x),idx) for (idx,x) in enumerate(a)] >>> diff [(2.5, 0), (4.7, 1), (1.0, 2), (1.6, 3)] >>> diff.sort() >>> diff [(1.0, 2), (1.6, 3), (2.5, 0), (4.7, 1)]
你会得到diff [0] [1]中最接近的值的索引
def finder(myList, target) diff = '' index = None for i,num in enumerate(myList): if abs(target - num) < diff: diff = abs(target - num) index = i return index
希望这可以帮助
编辑 :
如果你想要一个单线,那么你可能会更喜欢这个:
min(L, key=lambda x: abs(target-x))