如何在numpy数组中找到最接近且比给定值大的数?

7
我希望能在numpy数组中获取比我的搜索值大的最近值的索引。例如:findNearestAbove(np.array([0.,1.,1.4,2.]), 1.5)应该返回3(即2的索引)。
我知道我可以通过np.abs(a-value).argmin()来获取最近的索引,我发现min(a[np.where(a-value >= 0.)[0]])返回所需的数组值。因此,np.where(a == min(a[np.where(a-value >= 0.)[0]]))[0]可能会给我所需的索引。但是,这看起来有些复杂,并且我担心它在多维数组的情况下可能会出错。有没有改进这个方法的建议?

你的意思是“最近”的意思是“最左边的”吗? - kirelagin
2
你的数组总是按升序排列吗? - ali_m
澄清一下:“nearest” 意味着“按值排序”。另外:不,数组不一定是已排序的。 - maschu
4个回答

10

我相信你可以使用np.searchsorted来实现:

In [15]: np.searchsorted(a,[1.5,],side='right')[0]
Out[15]: 3

假设a是按升序排列的。

这种方法对于多维数组也不起作用,但我不确定在预期输出方面会如何使用。如果您可以举个例子,我可能能够将其适应到该目的。

注意:您还可以使用np.digitize来实现此目的,尽管它执行的是线性搜索而不是二进制搜索,因此对于某些输入大小,它可能比searchsorted慢得多,并且要求a是单调的:

In [25]: np.digitize([1.5,], a, right=True)[0]
Out[25]: 3

谢谢!当我确实处理排序数组时,这可能会很有帮助。使用案例是地理坐标:通常它们是一维的,但您也可以拥有“曲线网格”,在这种情况下,经度和纬度都存储为二维数组。我必须承认,在这种情况下,“find_nearest_above”的用例我还没有完全想清楚。这可能毫无意义。 - maschu
1
从v1.10版本开始,“np.digitize是基于np.searchsorted实现的”(引用文档)。这些函数之间实际上已经没有区别了。 - Mad Physicist
为什么当我输入side='left'时,它不会反向工作? - Peter.k

7
这里有一种方法(我假设你所说的“最近”是指数值而非位置):
import numpy as np

def find_nearest_above(my_array, target):
    diff = my_array - target
    mask = np.ma.less_equal(diff, 0)
    # We need to mask the negative differences and zero
    # since we are looking for values above
    if np.all(mask):
        return None # returns None if target is greater than any value
    masked_diff = np.ma.masked_array(diff, mask)
    return masked_diff.argmin()

结果:

>>> find_nearest_above(np.array([0.,1.,1.4,2.]), 1.5)
3
>>> find_nearest_above(np.array([0.,1.,1.4,-2.]), -1.5)
0
>>> find_nearest_above(np.array([0., 1, 1.4, 2]), 3)
>>> 

如果不能假定数组已排序,则这是最快的解决方案。 - ali_m
确实,这非常迷人。这里只有一个小故障:如果值大于最大数组值,则此函数返回索引零。因此,需要进行额外的检查:ind = masked_diff.argmin() ; if my_array[ind]>=target: ind = None ; return ind。或者是否有更有效的方法来解决这个问题? - maschu
if not np.any(mask): return - ali_m
感谢您的输入,我已更新我的答案。现在它可以正常工作了。 - Akavall

0

以下是我在查找数组中最接近但大于给定数字的值和索引时使用的解决方案(无法保证速度等方面):

def findNearestGreaterThan(searchVal, inputData):
    diff = inputData - searchVal
    diff[diff<0] = np.inf
    idx = diff.argmin()
    return idx, inputData[idx]

它也很容易适应最近但小于的情况:

def findNearestLessThan(searchVal, inputData):
    diff = inputData - searchVal
    diff[diff>0] = -np.inf
    idx = diff.argmax()
    return idx, inputData[idx]

-3

这是做这件事的正确方式:

>>> def argfind(array, predicate):
...     for i in xrange(array.shape[0]):
...         if predicate(array[i]):
...             return i
...     return False
...
>>> def find_nearest_above(array, value):
...     return argfind(array, lambda x: x > value)
...
>>> find_nearest_above(np.array([0.,1.,1.4,2.]), 1.5)
  > 3

这里的重点是,如果存在匹配值,当遇到该值时,您将获得答案。其他方法(包括在问题中提出的您自己的方法)将检查整个数组,这是一种浪费时间的做法。

假设数组确实已排序,np.searchsorted可以更快地完成这个任务。 - ali_m
@ali_m 是的,你可以确定,我听说过二分查找。但是你为什么认为数组是有序的呢? - kirelagin
好的,你的解决方案只有在数组已排序的情况下才有效。 - ali_m
@ali_m,问题在于对我来说,“nearest”意味着“最左边的”。正如我在评论中提到的那样。 - kirelagin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接