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

时间:2022-08-22 13:46:17

I found this post: Python: finding an element in an array

我发现这篇文章:Python:在数组中查找元素

and it's about returning the index of an array through matching the values.

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

On the other hand, what I am thinking of doing is similar but different. I would like to find the nearest value for the target value. For example I am looking for 4.2 but I know in the array there is no 4.2 but I want to return the index of the value 4.1 instead of 4.4.

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

What would be the fastest way of doing it?

这样做最快的方法是什么?

I am thinking of doing it the old way like how I used to do it with Matlab, which is using the array A where I want to get the index from to minus the target value and take the absolute of it, then select the min. Something like this:-

我正在考虑用旧的方式来做它,就像我以前用Matlab做的那样,它使用数组A,我希望从索引到减去目标值并取绝对值,然后选择min。像这样: -

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

That is Matlab code but I am newbie in Python so I am thinking, is there a fast way of doing it in Python?

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

Thank you so much for your help!

非常感谢你的帮助!

6 个解决方案

#1


30  

This is similar to using bisect_left, but it'll allow you to pass in an array of targets

这类似于使用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

Some explanation:

一些解释:

First the general case: idx = A.searchsorted(target) returns an index for each target such that target is between A[index - 1] and A[index]. I call these left and right so we know that left < target <= right. target - left < right - target is True (or 1) when target is closer to left and False (or 0) when target is closer to right.

首先是一般情况:idx = A.searchsorted(target)返回每个目标的索引,使得目标位于A [index - 1]和A [index]之间。我把它们称为左右,所以我们知道左

Now the special case: when target is less than all the elements of A, idx = 0. idx = np.clip(idx, 1, len(A)-1) replaces all values of idx < 1 with 1, so idx=1. In this case left = A[0], right = A[1] and we know that target <= left <= right. Therefor we know that target - left <= 0 and right - target >= 0 so target - left < right - target is True unless target == left == right and idx - True = 0.

现在特殊情况:当目标小于A的所有元素时,idx = 0.idx = np.clip(idx,1,len(A)-1)将idx <1的所有值替换为1,所以idx = 1。在这种情况下,left = A [0],right = A [1],我们知道target <= left <= right。因此我们知道目标 - 左<= 0和右 - 目标> = 0所以目标 - 左 <右 - 目标是真,除非目标="=左==右和idx" 真="0。

There is another special case if target is greater than all the elements of A, In that case idx = A.searchsorted(target) and np.clip(idx, 1, len(A)-1) replaces len(A) with len(A) - 1 so idx=len(A) -1 and target - left < right - target ends up False so idx returns len(A) -1. I'll let you work though the logic on your own.

如果target大于A的所有元素,还有另一种特殊情况。在这种情况下,idx = A.searchsorted(target)和np.clip(idx,1,len(A)-1)用len替换len(A) (A) - 1所以idx = len(A)-1和target - left

For example:

例如:

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])

#2


30  

The corresponding Numpy code is almost the same, except you use numpy.argmin to find the minimum index.

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

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

#3


6  

Well, more than 2 years have gone by and I have found a very simple implementation from this URL in fact: Find nearest value in numpy array

好吧,超过2年已经过去了,事实上我从这个URL找到了一个非常简单的实现:在numpy数组中查找最接近的值

The implementation is:

实施是:

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

Cheers!!

干杯!!

#4


4  

Tested and timed two solutions:

测试和定时两个解决方案:

idx = np.searchsorted(sw, sCut)

and

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

for computation in a time expensive method. timing was 113s for computation with the second solution, and 132s for computation with the first one.

用于计算时间昂贵的方法。使用第二种解决方案计算时间为113s,使用第一种解决方案计算时间为132s。

#5


2  

Possible solution:

可能的方法:

>>> 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)]

You'll have the index of nearest value in diff[0][1]

你将在diff [0] [1]中得到最近值的索引

#6


0  

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

Hope this helps

希望这可以帮助

EDIT:

编辑:

If you'd like a one-liner, then you might like this better:

如果你想要一个单行,那么你可能会更喜欢这个:

min(L, key=lambda x: abs(target-x))

#1


30  

This is similar to using bisect_left, but it'll allow you to pass in an array of targets

这类似于使用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

Some explanation:

一些解释:

First the general case: idx = A.searchsorted(target) returns an index for each target such that target is between A[index - 1] and A[index]. I call these left and right so we know that left < target <= right. target - left < right - target is True (or 1) when target is closer to left and False (or 0) when target is closer to right.

首先是一般情况:idx = A.searchsorted(target)返回每个目标的索引,使得目标位于A [index - 1]和A [index]之间。我把它们称为左右,所以我们知道左

Now the special case: when target is less than all the elements of A, idx = 0. idx = np.clip(idx, 1, len(A)-1) replaces all values of idx < 1 with 1, so idx=1. In this case left = A[0], right = A[1] and we know that target <= left <= right. Therefor we know that target - left <= 0 and right - target >= 0 so target - left < right - target is True unless target == left == right and idx - True = 0.

现在特殊情况:当目标小于A的所有元素时,idx = 0.idx = np.clip(idx,1,len(A)-1)将idx <1的所有值替换为1,所以idx = 1。在这种情况下,left = A [0],right = A [1],我们知道target <= left <= right。因此我们知道目标 - 左<= 0和右 - 目标> = 0所以目标 - 左 <右 - 目标是真,除非目标="=左==右和idx" 真="0。

There is another special case if target is greater than all the elements of A, In that case idx = A.searchsorted(target) and np.clip(idx, 1, len(A)-1) replaces len(A) with len(A) - 1 so idx=len(A) -1 and target - left < right - target ends up False so idx returns len(A) -1. I'll let you work though the logic on your own.

如果target大于A的所有元素,还有另一种特殊情况。在这种情况下,idx = A.searchsorted(target)和np.clip(idx,1,len(A)-1)用len替换len(A) (A) - 1所以idx = len(A)-1和target - left

For example:

例如:

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])

#2


30  

The corresponding Numpy code is almost the same, except you use numpy.argmin to find the minimum index.

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

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

#3


6  

Well, more than 2 years have gone by and I have found a very simple implementation from this URL in fact: Find nearest value in numpy array

好吧,超过2年已经过去了,事实上我从这个URL找到了一个非常简单的实现:在numpy数组中查找最接近的值

The implementation is:

实施是:

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

Cheers!!

干杯!!

#4


4  

Tested and timed two solutions:

测试和定时两个解决方案:

idx = np.searchsorted(sw, sCut)

and

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

for computation in a time expensive method. timing was 113s for computation with the second solution, and 132s for computation with the first one.

用于计算时间昂贵的方法。使用第二种解决方案计算时间为113s,使用第一种解决方案计算时间为132s。

#5


2  

Possible solution:

可能的方法:

>>> 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)]

You'll have the index of nearest value in diff[0][1]

你将在diff [0] [1]中得到最近值的索引

#6


0  

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

Hope this helps

希望这可以帮助

EDIT:

编辑:

If you'd like a one-liner, then you might like this better:

如果你想要一个单行,那么你可能会更喜欢这个:

min(L, key=lambda x: abs(target-x))