6

我有两个嵌套列表 A 和 B:

A = [[50,140],[51,180],[54,500],......]

B = [[50.1, 170], [51,200],[55,510].....]

每个内部列表中的第一个元素从 0 到大约 1e5,第 0 个元素从大约 50 到大约 700,这些元素是未排序的。我想要做的是遍历 A[n][1] 中的每个元素并在 B[n][1] 中找到最近的元素,但是在搜索最近的邻居时,我只想在定义的区间内搜索A[n][0] 正负 0.5。

我一直在使用这个功能:

def find_nearest_vector(array, value): 
   idx = np.array([np.linalg.norm(x+y) for (x,y) in array-value]).argmin()
   return array[idx]

例如,它会找到坐标A[0][:]和之间的最近邻居B[0][:]。但是,我需要将搜索范围限制在一个围绕值 A[0][0] 的一些小偏移的矩形内。另外,我不想重用元素 - 我想要在区间 A[n][0] +/- 0.5 内的每个值 A[n][1] 到 B[n][1] 之间的唯一双射。

我一直在尝试使用 Scipy 的 KDTree,但这会重用元素,我不知道如何限制搜索范围。实际上,我想沿特定轴在二维嵌套列表上进行一维 NNN 搜索,其中 NNN 搜索的邻域位于由每个内部列表中的第 0 个元素定义的超矩形内,加上或减去一些小位移.

4

2 回答 2

2

我使用numpy.argsort(), numpy.searchsorted(),numpy.argmin()进行搜索。

%pylab inline
import numpy as np
np.random.seed(0)
A = np.random.rand(5, 2)
B = np.random.rand(100, 2)
xaxis_range = 0.02
order = np.argsort(B[:, 0])
bx = B[order, 0]
sidx = np.searchsorted(bx, A[:, 0] - xaxis_range, side="right")
eidx = np.searchsorted(bx, A[:, 0] + xaxis_range, side="left")
result = []
for s, e, ay in zip(sidx, eidx, A[:, 1]):
    section = order[s:e]
    by = B[section, 1]
    idx = np.argmin(np.abs(ay-by))
    result.append(B[section[idx]])
result = np.array(result)

我绘制结果如下:

plot(A[:, 0], A[:, 1], "o")
plot(B[:, 0], B[:, 1], ".")
plot(result[:, 0], result[:, 1], "x")

输出:

在此处输入图像描述

于 2013-09-16T00:56:53.820 回答
0

我对您的问题的理解是,您正试图A[n][1]在另一组点中为每个点找到最接近的元素(B[i][1]仅限于 ifA[n][0]在 +/- 0.5 of 范围内的点B[i][0])。

我对 numpy 或 scipy 不熟悉,我确信他们的算法有更好的方法来做到这一点。

话虽如此,这是我O(a*b*log(a*b))及时的幼稚实现。

def main(a,b):
    for a_bound,a_val in a:
        dist_to_valid_b_points = {abs(a_val-b_val):(b_bound,b_val) for b_bound,b_val in b if are_within_bounds(a_bound,b_bound)}
        print get_closest_point((a_bound, a_val),dist_to_valid_b_points)

def are_within_bounds(a_bound, b_bound):
    return abs(b_bound-a_bound) < 0.5

def get_closest_point(a_point, point_dict):
    return (a_point, None if not point_dict else point_dict[min(point_dict, key=point_dict.get)])

main([[50,140],[51,180],[54,500]],[[50.1, 170], [51,200],[55,510]])产生以下输出:

((50, 140), (50.1, 170))
((51, 180), (51, 200))
((54, 500), None)
于 2013-09-15T21:04:27.893 回答