我有两个x-y坐标数组,我想找出一个数组中的每个点与另一个数组中的所有点之间的最小欧几里得距离。这些数组的大小不必相同。例如:
xy1=numpy.array(
[[ 243, 3173],
[ 525, 2997]])
xy2=numpy.array(
[[ 682, 2644],
[ 277, 2651],
[ 396, 2640]])
我当前的方法遍历xy1
中的每个坐标xy
,并计算该坐标与其他坐标之间的距离。
mindist=numpy.zeros(len(xy1))
minid=numpy.zeros(len(xy1))
for i,xy in enumerate(xy1):
dists=numpy.sqrt(numpy.sum((xy-xy2)**2,axis=1))
mindist[i],minid[i]=dists.min(),dists.argmin()
有没有办法消除for循环,并以某种方式在两个数组之间进行逐个元素的计算?我设想生成一个距离矩阵,它可以找到每行或每列中的最小元素。
另一种看待这个问题的方式。假设我将xy1
(长度m)和xy2
(长度p)连接成xy
(长度n),然后存储原始数组的长度。从理论上讲,我应该能够从这些坐标生成一个n x n距离矩阵,从中我可以获得一个m x p子矩阵。有没有一种方法可以有效地生成这个子矩阵?
9条答案
按热度按时间p5fdfcr11#
(几个月后)
scipy.spatial.distance.cdist( X, Y )
给出了所有的距离对,对于X和Y,2暗,3暗...它还做了22种不同的规范,详细的here。
l3zydbqr2#
要计算距离的m乘p矩阵,应该是这样的:
.outer
调用生成两个这样的矩阵(沿两个轴的标量差),.hypot
调用将它们转换成一个形状相同的矩阵(标量欧几里得距离)。ohfgkhjo3#
被接受的答案没有完全解决这个问题,该问题要求找出两个点集合之间的最小距离,而不是两个集合中每个点之间的距离。
虽然原始问题的直接解决方案确实包括计算每一对之间的距离,然后找到最小的一对,但如果一个人只对最小距离感兴趣,那么这并不是必要的。对于后一个问题,存在一个更快的解决方案。
所有建议的解决方案的运行时间都可以扩展为
m*p = len(xy1)*len(xy2)
。这对于小型数据集是可以的,但是可以编写可扩展为m*log(p)
的最佳解决方案,从而为大型xy2
数据集带来巨大的节省。使用scipy.spatial.KDTree可以实现这种最佳的执行时间扩展,如下所示
其中
mindist
是xy1
中的每个点与xy2
中的点集之间的最小距离62lalag44#
为了你想要做的事:
sqrt
、做正方形等,可以使用numpy.hypot
:unftdfkk5#
jaql4c8m6#
我认为下面的功能也适用。
说明
假设
X
和Y
的每一行都是两组点的坐标。让它们的大小分别为
m X p
和p X n
。结果将产生一个大小为
m X n
的数值数组,其中(i, j)
第x项分别是X
和Y
的i
行和j
行之间的距离。qeeaahzv7#
我强烈推荐使用一些内置的方法来计算平方和根,因为它们是为优化计算方式而定制的,并且非常安全,防止溢出。
@Alex Answer下面是溢出方面最安全的,也应该是非常快的。此外,对于单点,您可以使用math.supt,它现在支持2个以上的维度。
安全隐患
overflow/underflow/speeds
zed5wv108#
我认为最直接和高效**的解决方案是这样做:
68bkxrlz9#
虽然这里的许多答案都很棒,但还有一种方法没有在这里提到,它使用
numpy
的矢量化/广播属性来计算两个不同长度的不同数组的每个点之间的距离(如果需要,还可以计算最接近的匹配)。我在这里发布它是因为它可以非常方便地掌握广播,并且在保持非常高效的同时也有效地解决了这个问题。假设您有两个如下所示的数组:
您不能执行操作
a-b
:NumPy使用operands could not be broadcast together with shapes (6,2) (4,2)
抱怨。允许广播的诀窍是手动为NumPy添加一个要一起广播的维度。通过将维度2
保留在两个重塑后的数组中,NumPy知道它必须在该维度上执行操作。distance_matrix
的形状为(6,4)
:对于a
中的每个点,计算到b
中所有点的距离。然后,如果您想要“一个数组中的每个点与另一个数组中的所有点之间的最小欧几里得距离”,您可以这样做:这将返回
b
中最接近a
的每个点的点的索引。