繁体   English   中英

如何计算数组每行中点之间的距离

[英]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.repeatnp.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

TL;博士

制作点的索引

有很多方法可以为您想要获取的每对点创建索引对。 但它们来自哪里? 在每种情况下,从邻接矩阵开始构建它们都是一个好主意。

情况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)

我将手动制作xy (不加掩码)作为其他人的练习。

应用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM