查找距离数组2的元素最近的数组1的元素

时间:2016-06-15 17:07:46

标签: python arrays algorithm sorting numpy

This answer解释了如何以对大型数组有效的方式(略微修改)找到单点的最近(已排序)数组元素:

def arg_nearest(array, value):
    idx = np.searchsorted(array, value, side="left")
    if idx > 0 and (idx == len(array) or math.fabs(value - array[idx-1]) < math.fabs(value - array[idx])):
        return idx-1
    else:
        return idx

相反,如果我们想要找到最接近点 set 的数组元素(即第二个数组);除了使用for-loop之外,还有效率(通过速度,对于大型数组)扩展它的方法吗?

一些测试用例:

>>> xx = [0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5]
>>> yy = [1, 2, 3, 4, 5]
>>> of_x_nearest_y(xx, yy)
[0.5, 2.0, 3.1, 3.9, 5.1]

>>> xx = [0.2, 0.8, 1.3, 1.5, 2.0, 3.1, 3.8, 3.9, 4.5, 5.1, 5.5]
>>> yy = [-2, -1, 4.6, 5.8]
>>> of_x_nearest_y(xx, yy)
[0.2, 0.2, 4.5, 5.5]

编辑:假设两个数组都已排序,你可以通过排除已经匹配的值以下的值来比完全天真的for循环更好地做,即

def args_nearest(options, targets):
    locs = np.zeros(targets.size, dtype=int)
    prev = 0
    for ii, tt in enumerate(targets):
        locs[ii] = prev + arg_nearest(options[prev:], tt)
        prev = locs[ii]
    return locs

1 个答案:

答案 0 :(得分:1)

您可以进行一些更改,以便为value中的元素数组扩展它,就像这样 -

idx = np.searchsorted(xx, yy, side="left").clip(max=xx.size-1)
mask = (idx > 0) &  \
       ( (idx == len(xx)) | (np.fabs(yy - xx[idx-1]) < np.fabs(yy - xx[idx])) )
out = xx[idx-mask]

<强>解释

命名法:array是我们希望在value中放置元素以保持array的排序特性的数组。

将单个元素的解决方案扩展到许多元素以进行搜索所需的更改:

1]剪切从idx获得的索引数组np.searchsortedarray.size-1的{​​{1}},因为value中的元素大于array的最大值,我们需要idx使array可转位。

2]引入numpy替换math以矢量化方式执行这些操作。

3]用idx - mask的技巧替换条件语句。在这种情况下,内部Python会将mask上转换为int数组,以匹配idx的数据类型。因此,所有True元素都变为1,因此对于True元素,我们实际上会idx-1,这是IF条件语句的True个案例。原始代码。