【问题标题】:How to find nearest value that is greater in numpy array?如何在numpy数组中找到更大的最近值?
【发布时间】:2013-06-11 16:26:33
【问题描述】:

我想在一个大于我的搜索值的 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] 可能会给我所需的索引。但是,这看起来相当复杂,我担心它可能会在多维数组的情况下中断。有什么建议可以改进吗?

【问题讨论】:

  • “最近”是指“最左边”?
  • 你的数组总是按升序排列吗?
  • 澄清一下:“最近”的意思是“按价值”。另外:否 - 数组不一定是排序的。

标签: python numpy indexing


【解决方案1】:

我相信您可以为此使用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 的用例。这很可能没有意义。
  • 从 v1.10 开始,“np.digitize 是根据 np.searchsorted 实现的。” (引用文档)。功能之间实际上不再有区别。
  • 为什么当我输入 side='left' 时它不起作用?
【解决方案2】:

这是一种方法(我假设您的最近是指价值而不是位置)

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

【讨论】:

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

在找到数组中最近但大于数字的值和索引时,这是一个非常适合我的解决方案(在速度等方面没有承诺):

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]

【讨论】:

    【解决方案4】:

    这是正确的方法:

    >>> 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 对我来说,“最近”意味着“最左边”。正如我在对该问题的评论中提到的那样。
    猜你喜欢
    • 2014-04-03
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-27
    • 2014-04-26
    • 2019-02-02
    相关资源
    最近更新 更多