我有两个分别为A
和B
且形状为(m, 2)
的数组(n, 2)
和n >> m
。就我而言,n = 8013
和m = 71
。每个阵列的每一行(x, y)
代表天文图像中点源的坐标,以像素为单位。 A
中的所有行的值与B
中的某些行的值非常接近,但并不完全相同。在某些情况下,差异是一些小数,在其他情况下,可能是一或两个整数,例如A
中的一行是(1158, 1304.8974)
,B中相应的行是(1160, 1304.6578)
。
我的问题是:如何找到B
中元素最接近A
中元素的索引?
我的第一次尝试是:
matched = []
indexes = []
for k in np.arange(0, len(A)):
idx = np.where((B[:, 0].astype(int) == A[k, 0].astype(int)) &
(B[:, 1].astype(int) == A[k, 1].astype(int)))
matched.append(B[idx])
indexes.append(idx)
但是它仅返回A
中行的索引,其整数与B
中的元素完全相同,因此并不匹配所有项目。如果删除astype(int)
,则匹配项更少。
我尝试过的第二次尝试是:
value = A[0]
X = np.abs(B - value)
idx = np.where(X == X.min())
B[idx[0]]
但是它只计算x
或y
列中的最接近值,而不是两者都计算。这意味着如果我要匹配的A
中有一行,例如(1230, 980)
,而B
中有两行,例如(3450, 981)
和{{1} },后者是正确的匹配项和预期的输出,第二个实现返回元素(1233, 975)
作为与(3450, 981)
的正确匹配项,因为点(1230, 980)
更接近y = 980
而不是y = 981
。
答案 0 :(得分:0)
您可以将idx定义的大小写更改为可接受的范围,如下所示:
idx = np.where((B[:, 0].astype(int) >= A[k, 0].astype(int) - 3) & (B[:, 0].astype(int) <= a(k,0].astype(int + 3)) & (B[:, 1].astype(int) == A[k, 1].astype(int)))
答案 1 :(得分:0)
您正在寻找最常规的距离:欧几里得。
由于您的数字大约是1万乘100,因此在任何合理的现代硬件上,计算时间之间的距离或内存都不会特别昂贵。如果价格昂贵,我会推荐scipy.spatial.KDTree
之类的东西,它可以有效地实现适当的空间排序。
获取每组点之间距离的最简单方法是使用scipy.spatial.distance.cdist
。这并不总是和“手动”计算距离一样快,但是足够快:
dist = cdist(A, B)
dist
是一个(m, n)
数组。您可以使用np.argmin
在每一行中找到最小距离的索引:
idx = np.argmin(dist, axis=1)
B
的对应元素是
matches = B[idx, :]
这假设您的输入数组A
和B
是开始的numpy数组。如果不是这种情况,请先将它们分成数组:
A = np.array(A)
B = np.array(B)
如果要“手动”实现距离,这会更快,则可以使用broadcasting来计算平方差之和的平方根:
dist = np.sqrt(sum((A.reshape(-1, 1, 2) - B.reshape(1, -1, 2))**2, axis=-1))
如果只想找到最小值,则不需要最终的平方根,因为平方根单调增加,并且平方距离的最小值出现在最小距离上。