在 Python 中查找最近的值并返回数组的索引

Posted

技术标签:

【中文标题】在 Python 中查找最近的值并返回数组的索引【英文标题】:Finding the nearest value and return the index of array in Python 【发布时间】:2012-02-13 10:18:32 【问题描述】:

我发现了这个帖子:Python: finding an element in an array

它是关于通过匹配值返回数组的索引。

另一方面,我想做的事情相似但不同。我想找到目标值的最接近值。例如,我正在寻找 4.2,但我知道数组中没有 4.2,但我想返回值 4.1 而不是 4.4 的索引。

最快的方法是什么?

我正在考虑用旧的方式来做这件事,就像我以前用 Matlab 做的那样,它使用数组 A,我想从中获取索引减去目标值并取其绝对值,然后选择分钟。像这样的东西:-

[~,idx] = min(abs(A - target))

这是 Matlab 代码,但我是 Python 新手,所以我在想,有没有一种在 Python 中快速的方法?

非常感谢您的帮助!

【问题讨论】:

***.com/questions/2566412/… 和 ***.com/questions/6065697/… 可能有用。 【参考方案1】:

对应的 Numpy 代码几乎相同,只是你使用numpy.argmin 来查找最小索引。

idx = numpy.argmin(numpy.abs(A - target))

【讨论】:

如果输入数组按排序顺序,numpy.searchsorted 也很方便(而且效率更高)。 OP 没有具体说明,但我想我会指出,如果 A = [4.1, 4.4, 5, 4.1]target = 4.2。此代码将仅返回 idx = 0 而不是 idx = [0, 3]。是否唯一的方法是循环返回 A,将每个值与 idx = 0 的值进行比较,以确定是否还有其他值? @sgallen:发布的 Matlab 代码 OP 给出了idx = 1(Matlab 索引是从 1 开始的),所以我想其他的都不需要。 正如@JoeKington 已经提到的那样,searchsorted 如果对 A 进行排序会更快,但它也可以将目标数组作为参数,因此如果您需要重复此操作超过一个目标。如果这对你有用,请告诉我,我会写下来作为答案。 老实说,我使用这个函数来搜索排序数组。如果你能指导我,我将非常感激,@Bago。太感谢了!你们真的很有帮助。【参考方案2】:
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))

【讨论】:

【参考方案3】:

可能的解决方案:

>>> 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] 中获得最接近值的索引

【讨论】:

【参考方案4】:

这类似于使用 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]之间。我称这些为leftright,所以我们知道left &lt; target &lt;= right。当目标更接近lefttarget - left &lt; right - targetTrue(或1),当目标更接近rightFalse(或0)。

现在是特殊情况:当target 小于Aidx = 0 的所有元素时。 idx = np.clip(idx, 1, len(A)-1)idx idx=1。在这种情况下left = A[0]right = A[1],我们知道target &lt;= left &lt;= right。因此我们知道target - left &lt;= 0right - target &gt;= 0 所以target - left &lt; right - targetTrue 除非target == left == rightidx - True = 0

如果target大于A的所有元素还有另一种特殊情况,在这种情况下idx = A.searchsorted(target)np.clip(idx, 1, len(A)-1) len(A)替换len(A) - 1所以idx=len(A) -1target - left &lt; 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])

【讨论】:

非常感谢@Bago!我正在尝试理解代码,但idx -= target - left &lt; right - target 部分存在问题。我是 Python 新手,所以我首先测试了 target - left &lt; right - target,它们返回了 TrueFalse 的范围。我使用 idx 减去结果,得到一个稍微失真的数组。例如,原始索引 0 变为 -1。我在这里错过了什么吗?【参考方案5】:

测试并计时了两种解决方案:

idx = np.searchsorted(sw, sCut)

idx = np.argmin(np.abs(sw - sCut))

用于以耗时的方法进行计算。 第二个解决方案的计算时间为113s,第一个解决方案的计算时间为132s

【讨论】:

请注意,这些返回不同的结果。 np.argmin(np.abs(np.array([1, 2, 3, 4]) - 2.1)) 返回 1,其中 np.searchsorted([1, 2, 3, 4], 2.1) 返回 2... np.searchsorted 返回插入位置以保留顺序,因此它返回目标后第一个值的索引,可能不是最近的值。使用最小化abs(value-target) 的任何方法实际上是在找到可能高于或低于目标的最接近的值。根据您的需要,两者都可能合适,但它们并不等效。【参考方案6】:

嗯,2 年多过去了,实际上我从这个 URL 中找到了一个非常简单的实现:Find nearest value in numpy array

实现是:

def getnearpos(array,value):
    idx = (np.abs(array-value)).argmin()
    return idx   

干杯!!

【讨论】:

以上是关于在 Python 中查找最近的值并返回数组的索引的主要内容,如果未能解决你的问题,请参考以下文章

C++:查找数组中最接近的值

ActionScript 3 AS3在数组中搜索值并返回其位置索引

AS3在数组中搜索一个值并返回它的位置索引

[数据库基础]——索引详解

用MATLAB怎么在数列中找到需要的值并返回在数列中的位置

如何在数组中查找一个值并使用 PHP 数组函数将其删除?