在 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]
之间。我称这些为left
和right
,所以我们知道left < target <= right
。当目标更接近left
时target - left < right - target
为True
(或1),当目标更接近right
时False
(或0)。
现在是特殊情况:当target
小于A
、idx = 0
的所有元素时。 idx = np.clip(idx, 1, len(A)-1)
将 idx
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)
替换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])
【讨论】:
非常感谢@Bago!我正在尝试理解代码,但idx -= target - left < right - target
部分存在问题。我是 Python 新手,所以我首先测试了 target - left < right - target
,它们返回了 True
和 False
的范围。我使用 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 中查找最近的值并返回数组的索引的主要内容,如果未能解决你的问题,请参考以下文章