Python - 根据距离关联两个点列表
Python - Associate two list of points based on distance
我有两组 n 个点,作为 Numpy 数组,顺序随机。我必须根据距离 (L2) 将两个列表之间的点相关联,以便 list1 中的每个点都得到一个且唯一的对应点,距离 list2 最近。
我的问题:就计算时间而言最快的方法是什么?
现在,我计算对称交叉范数矩阵(使用 scipy.spatial.distance_matrix),然后通过循环从那里对点进行排序,以找到整个矩阵中的最低范数矩阵。然后删除相应的行和列并迭代直到矩阵为空。我想知道是否有已知的更快的方法。
[编辑]:这是我得到的代码和示例
import numpy as np
import numpy.ma as ma
import matplotlib.pyplot as plt
from scipy.spatial import distance_matrix
rng = np.random.default_rng()
lst1 = rng.random((10, 2))
lst2 = lst1 + 0.1 * rng.standard_normal(lst1.shape) # rng.random((10, 2))
mask = np.zeros((len(lst1), len(lst2)), dtype=bool)
dst = ma.array(distance_matrix(lst1, lst2), mask=mask)
ord_lst1 = []
ord_lst2 = []
for i in range(min(len(lst1), len(lst2))):
index = np.unravel_index(np.argmin(dst), shape=dst.shape)
ord_lst1.append(lst1[index[0], :])
ord_lst2.append(lst2[index[1], :])
dst[index[0], :] = ma.masked
dst[:, index[1]] = ma.masked
fig = plt.figure()
plt.grid(True)
plt.scatter(x=lst1[:, 0], y=lst1[:, 1], label="list1")
plt.scatter(x=lst2[:, 0], y=lst2[:, 1], label="list2")
for p1, p2 in zip(ord_lst1, ord_lst2):
plt.plot((p1[0], p2[0]), (p1[1], p2[1]), "--", color="black")
plt.legend()
输出如下:
如您所见,两个非常间隔的点之间的巨大关联可能会令人不安。但是list1在(0.4,0.6)中的点与右上角的list2最接近,因此建立关联并排除这两个点进一步关联。
谢谢:)
调查scipy.spatial.KDTree
https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.html
从列表 2 构建 kdTree,并在列表 1 中的每个点查询它
以下代码段未经测试,因此可能需要调试。它应该是您自己设计的开始
#L1 is numpy array with shape (N,2)
#L2 is numpy array with shape (N,2)
import scipy.spatial
tree=scipy.spatial.KDTree(L2)
assoc=[]
for I1,point in enumerate(L1):
_,I2 = tree.query(point,k=1)
assoc.append((I1,I2))
assoc
变量包含作为索引元组列表的最终关联
编辑:为了帮助解决非唯一关联问题,第一步可能是 运行 KDtree 算法两次,一次使用“主列表”L1,一次使用“主列表” list" L2,然后只保留两者之间共有的关联。你可以将剩余的点作为特殊情况处理。
我有两组 n 个点,作为 Numpy 数组,顺序随机。我必须根据距离 (L2) 将两个列表之间的点相关联,以便 list1 中的每个点都得到一个且唯一的对应点,距离 list2 最近。
我的问题:就计算时间而言最快的方法是什么?
现在,我计算对称交叉范数矩阵(使用 scipy.spatial.distance_matrix),然后通过循环从那里对点进行排序,以找到整个矩阵中的最低范数矩阵。然后删除相应的行和列并迭代直到矩阵为空。我想知道是否有已知的更快的方法。
[编辑]:这是我得到的代码和示例
import numpy as np
import numpy.ma as ma
import matplotlib.pyplot as plt
from scipy.spatial import distance_matrix
rng = np.random.default_rng()
lst1 = rng.random((10, 2))
lst2 = lst1 + 0.1 * rng.standard_normal(lst1.shape) # rng.random((10, 2))
mask = np.zeros((len(lst1), len(lst2)), dtype=bool)
dst = ma.array(distance_matrix(lst1, lst2), mask=mask)
ord_lst1 = []
ord_lst2 = []
for i in range(min(len(lst1), len(lst2))):
index = np.unravel_index(np.argmin(dst), shape=dst.shape)
ord_lst1.append(lst1[index[0], :])
ord_lst2.append(lst2[index[1], :])
dst[index[0], :] = ma.masked
dst[:, index[1]] = ma.masked
fig = plt.figure()
plt.grid(True)
plt.scatter(x=lst1[:, 0], y=lst1[:, 1], label="list1")
plt.scatter(x=lst2[:, 0], y=lst2[:, 1], label="list2")
for p1, p2 in zip(ord_lst1, ord_lst2):
plt.plot((p1[0], p2[0]), (p1[1], p2[1]), "--", color="black")
plt.legend()
输出如下:
如您所见,两个非常间隔的点之间的巨大关联可能会令人不安。但是list1在(0.4,0.6)中的点与右上角的list2最接近,因此建立关联并排除这两个点进一步关联。
谢谢:)
调查scipy.spatial.KDTree https://docs.scipy.org/doc/scipy/reference/generated/scipy.spatial.KDTree.html
从列表 2 构建 kdTree,并在列表 1 中的每个点查询它
以下代码段未经测试,因此可能需要调试。它应该是您自己设计的开始
#L1 is numpy array with shape (N,2)
#L2 is numpy array with shape (N,2)
import scipy.spatial
tree=scipy.spatial.KDTree(L2)
assoc=[]
for I1,point in enumerate(L1):
_,I2 = tree.query(point,k=1)
assoc.append((I1,I2))
assoc
变量包含作为索引元组列表的最终关联
编辑:为了帮助解决非唯一关联问题,第一步可能是 运行 KDtree 算法两次,一次使用“主列表”L1,一次使用“主列表” list" L2,然后只保留两者之间共有的关联。你可以将剩余的点作为特殊情况处理。