[英]How can I calculate distance between points in each row of an array
我有一个这样的数组,我必须找到每个点之间的距离。 如何使用 numpy 在 python 中执行此操作?
[ 8139, 115665],
[ 8132, 126563],
[ 8193, 113938],
[ 8193, 123714],
[ 8156, 120291],
[ 8373, 125253],
[ 8400, 131442],
[ 8400, 136354],
[ 8401, 129352],
[ 8439, 129909],
[ 8430, 135706],
[ 8430, 146359],
[ 8429, 139089],
[ 8429, 133243]```
您可以使用np.repeat
和np.tile
创建所有组合,然后计算欧几里得距离:
xy = np.array([[8139, 115665], [8132, 126563], [8193, 113938], [8193, 123714],
[8156, 120291], [8373, 125253], [8400, 131442], [8400, 136354],
[8401, 129352], [8439, 129909], [8430, 135706], [8430, 146359],
[8429, 139089], [8429, 133243]])
a = np.repeat(xy, len(xy), axis=0)
b = np.tile(xy, [len(xy), 1])
d = np.sqrt(np.sum((a - b) ** 2, axis=1))
d
的 output 为 (196,),即 14 x 14。
更新
但我必须在 function 中做到这一点。
def distance(xy):
a = np.repeat(xy, len(xy), axis=0)
b = np.tile(xy, [len(xy), 1])
return np.sqrt(np.sum((a - b) ** 2, axis=1))
d = distance(xy)
让我们将此问题最小化为 4 点:
points = np.array([[8139, 115665], [8132, 126563], [8193, 113938], [8193, 123714]])
一般来说,你需要做2个步骤:
np.hypot
。有很多方法可以为您想要获取的每对点创建索引对。 但它们来自哪里? 在每种情况下,从邻接矩阵开始构建它们都是一个好主意。
情况1
以最常见的方式,您可以像这样开始构建它:
adjacency = np.ones(shape=(len(points), len(points)), dtype=bool)
>>> adjacency
[[ True True True True]
[ True True True True]
[ True True True True]
[ True True True True]]
它对应于您需要采取的索引,如下所示:
adjacency_idx_view = np.transpose(np.nonzero(adjacency))
for n in adjacency_idx_view.reshape(len(points), len(points), 2):
>>> print(n.tolist())
[[0, 0], [1, 0], [2, 0], [3, 0]]
[[0, 1], [1, 1], [2, 1], [3, 1]]
[[0, 2], [1, 2], [2, 2], [3, 2]]
[[0, 3], [1, 3], [2, 3], [3, 3]]
这就是你收集它们的方式:
x, y = np.nonzero(adjacency)
>>> np.transpose([x, y])
array([[0, 0],
[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 1],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 2],
[2, 3],
[3, 0],
[3, 1],
[3, 2],
[3, 3]], dtype=int64)
也可以像@ Corralien 的回答那样手动完成:
x = np.repeat(np.arange(len(points)), len(points))
y = np.tile(np.arange(len(points)), len(points))
案例2
在以前的情况下,每对点都是重复的。 还有点重复的对。 一个更好的选择是忽略这些过多的数据,只取第一个点的索引小于第二个点的索引的对:
adjacency = np.less.outer(np.arange(len(points)), np.arange(len(points)))
>>> print(adjacency)
[[False True True True]
[False False True True]
[False False False True]
[False False False False]]
x, y = np.nonzero(adjacency)
这没有被广泛使用。 尽管这超出了np.triu_indices
的范围。 因此,作为替代方案,我们可以使用:
x, y = np.triu_indices(len(points), 1)
这导致:
>>> np.transpose([x, y])
array([[0, 1],
[0, 2],
[0, 3],
[0, 4],
[1, 2],
[1, 3],
[1, 4],
[2, 3],
[2, 4],
[3, 4]])
案例 3您也可以尝试仅省略成对的重复点,并留下点对被交换。 与案例 1一样,它需要 2x memory 和消耗时间,所以我将其仅用于演示目的:
adjacency = ~np.identity(len(points), dtype=bool)
>>> adjacency
array([[False, True, True, True],
[ True, False, True, True],
[ True, True, False, True],
[ True, True, True, False]])
x, y = np.nonzero(adjacency)
>>> np.transpose([x, y])
array([[0, 1],
[0, 2],
[0, 3],
[1, 0],
[1, 2],
[1, 3],
[2, 0],
[2, 1],
[2, 3],
[3, 0],
[3, 1],
[3, 2]], dtype=int64)
我将手动制作x
和y
(不加掩码)作为其他人的练习。
np.hypot
而不是np.sqrt(np.sum((a - b) ** 2, axis=1))
你可以做np.hypot(np.transpose(a - b))
。 我将案例 2作为我的索引生成器:
def distance(points):
x, y = np.triu_indices(len(points), 1)
x_coord, y_coord = np.transpose(points[x] - points[y])
return np.hypot(x_coord, y_coord)
>>> distance(points)
array([10898.00224812, 1727.84403231, 8049.18113848, 12625.14736548,
2849.65296133, 9776. ])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.