问题描述
这个答案解释了如何找到距离单点,以一种对大型数组有效的方式(稍作修改):
def arg_nearest(array, value):idx = np.searchsorted(array, value, side="left")如果 idx >0 和 (idx == len(array) 或 math.fabs(value - array[idx-1])
如果相反,我们想要找到最接近集合点的数组元素(即第二个数组);除了使用 for 循环之外,是否有有效的(速度,对于大型数组)方法来扩展它?
一些测试用例:
>>>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(选项,目标):locs = np.zeros(targets.size, dtype=int)上一个 = 0对于 ii, tt in enumerate(targets):locs[ii] = prev + arg_nearest(options[prev:], tt)上一个 = locs[ii]返回位置
你可以做一些改变来扩展 value
中的元素数组,就像这样 -
idx = np.searchsorted(xx, yy, side="left").clip(max=xx.size-1)掩码 = (idx > 0) &\( (idx == len(xx)) | (np.fabs(yy - xx[idx-1]) < np.fabs(yy - xx[idx])) )out = xx[idx-掩码]
说明
命名法:array
是我们希望在其中放置来自 value
的元素以保持 array
的排序性质的数组.>
将单个元素的解决方案扩展到多个元素以进行搜索所需的更改:
1] 最大剪辑从 np.searchsorted
获得的索引数组 idx
.array.size-1
,因为对于value
中大于array
最大值的元素,我们需要使idx
可被 array
索引.
2] 引入 numpy
来替换 math
以矢量化方式执行这些操作.
3] 用idx - mask
的技巧替换条件语句.在这种情况下,Python 内部会将 mask
向上转换为 int
数组以匹配 idx
的数据类型.因此,所有 True
元素都变成了 1
,因此对于 True
元素,我们将有效地拥有 idx-1
,即是原始代码中 IF 条件语句的 True
情况.
This answer explains how to find the nearest (sorted) array element to a single point, in a manner efficient for large arrays (slightly modified):
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
If, instead, we want to find the array elements nearest a set of points (i.e. a second array); are there efficient (by speed, for large arrays) ways of extending this besides using a for-loop?
Some test cases:
>>> 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]
Edit: assuming both arrays are sorted, you can do a little better than a completely naive for-loop by excluding values below those already matched, i.e.
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
You can make few changes to extend it for an array of elements in value
, like so -
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]
Explanation
Nomenclature : array
is the array in which we are looking to place elements from value
to maintain the sorted nature of array
.
Changes needed to extend the solution for a single element to many elements for searching :
1] Clip the indices array idx
obtained from np.searchsorted
at a max. of array.size-1
, because for elements in value
that are larger than the maximum of array
, we need to make idx
indexable by array
.
2] Introduce numpy
to replace math
to do those operations in a vectorized manner.
3] Replace the conditional statement by the trick of idx - mask
. In this case, internally Python would up-convert mask
to an int
array to match up with the datatype of idx
. Thus, all the True
elements become 1
and thus for True
elements we would effectively have idx-1
, which is the True
case of the IF conditional statement in the original code.
这篇关于查找最接近数组 2 元素的数组 1 中的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!