How to find closest elements in two array?
我有两个numpy数组,比如
像:
1 2 | X [ 84.04467948 52.42447842 39.13555678 21.99846595] y [ 78.86529444 52.42447842 38.74910101 21.99846595] |
或者可以是:
1 2 | X [ 84.04467948 60 52.42447842 39.13555678] y [ 78.86529444 52.42447842 38.74910101 21.99846595] |
我想定义一个函数来查找两个数组中的对应索引,就像第一种情况:
y[0] 对应X[0] ,y[1] 对应X[1] ,y[2] 对应X[2] ,y[3] 对应X[3] 。
在第二种情况下:
y[0] 对应X[0] ,y[1] 对应X[2] ,y[2] 对应X[3] 。- 和
y[3] 对应于X[1] 。
我不能写一个函数来完全解决这个问题,请帮忙。
使用此答案https://stackoverflow.com/a/8929827/3627387和https://stackoverflow.com/a/12141207/3627387
固定的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | def find_closest(alist, target): return min(alist, key=lambda x:abs(x-target)) X = [ 84.04467948, 52.42447842, 39.13555678, 21.99846595] Y = [ 78.86529444, 52.42447842, 38.74910101, 21.99846595] def list_matching(list1, list2): list1_copy = list1[:] pairs = [] for i, e in enumerate(list2): elem = find_closest(list1_copy, e) pairs.append([i, list1.index(elem)]) list1_copy.remove(elem) return pairs |
您可以从预计算距离矩阵开始,如本答案所示:
1 2 3 4 5 6 | import numpy as np X = np.array([84.04467948,60.,52.42447842,39.13555678]) Y = np.array([78.86529444,52.42447842,38.74910101,21.99846595]) dist = np.abs(X[:, np.newaxis] - Y) |
号
现在可以计算沿一个轴的最小值(我选择了
1 | potentialClosest = dist.argmin(axis=1) |
这仍然可能包含重复项(在您的案例2中)。为了检查这一点,您可以使用
1 | closestFound, closestCounts = np.unique(potentialClosest, return_counts=True) |
。
现在您可以通过检查
1 2 3 | missingPartnerIndex = np.where( np.in1d(np.arange(Y.shape[0]), closestFound)==False )[0][0] |
您可以在一个循环中进行匹配(即使使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | partners = np.empty_like(X, dtype=int) nonClosePartnerFound = False for i in np.arange(X.shape[0]): if closestCounts[closestFound==potentialClosest[i]][0]==1: # A unique partner was found partners[i] = potentialClosest[i] else: # Partner is not unique if nonClosePartnerFound: partners[i] = potentialClosest[i] else: if np.argmin(dist[:, potentialClosest[i]]) == i: partners[i] = potentialClosest[i] else: partners[i] = missingPartnerIndex nonClosePartnerFound = True print(partners) |
。
只有当一对不接近时,这个答案才有效。如果不是这样,您必须定义如何为多个非关闭元素找到正确的合作伙伴。遗憾的是,它既不是一个非常通用的解决方案,也不是一个非常好的解决方案,但希望您能找到一个有用的起点。
似乎最好的方法是对两个数组(nlog(n))进行预排序,然后像遍历两个数组一样执行合并。它绝对比你在评论中指出的nn快。
下面简单地打印两个数组的相应索引,正如您在问题中所做的那样,因为我不确定您希望函数提供什么输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | X1 = [84.04467948, 52.42447842, 39.13555678, 21.99846595] Y1 = [78.86529444, 52.42447842, 38.74910101, 21.99846595] X2 = [84.04467948, 60, 52.42447842, 39.13555678] Y2 = [78.86529444, 52.42447842, 38.74910101, 21.99846595] def find_closest(x_array, y_array): # Copy x_array as we will later remove an item with each iteration and # require the original later remaining_x_array = x_array[:] for y in y_array: differences = [] for x in remaining_x_array: differences.append(abs(y - x)) # min_index_remaining is the index position of the closest x value # to the given y in remaining_x_array min_index_remaining = differences.index(min(differences)) # related_x is the closest x value of the given y related_x = remaining_x_array[min_index_remaining] print 'Y[%s] corresponds to X[%s]' % (y_array.index(y), x_array.index(related_x)) # Remove the corresponding x value in remaining_x_array so it # cannot be selected twice remaining_x_array.pop(min_index_remaining) |
。
然后输出以下内容
1 2 3 4 5 | find_closest(X1,Y1) Y[0] corresponds to X[0] Y[1] corresponds to X[1] Y[2] corresponds to X[2] Y[3] corresponds to X[3] |
和
1 2 3 4 5 | find_closest(X2,Y2) Y[0] corresponds to X[0] Y[1] corresponds to X[2] Y[2] corresponds to X[3] Y[3] corresponds to X[1] |
。
希望这有帮助。