【问题标题】:Calculate distances among a set of coordinates计算一组坐标之间的距离
【发布时间】:2021-04-05 10:51:24
【问题描述】:

有没有更有效的方法来计算给定点集之间的欧几里得距离?

这是我使用的代码:

def all_distances(position):
    distances = np.zeros((N_circles, N_circles))
    for i in range(N_circles):
        for j in range(i, N_circles):
            distances[i][j]=calculate_distance(position[i], position[j])
    return distances

def calculate_distance(p1, p2):
    return math.sqrt((p1[0]-p2[0])**2+(p1[1]-p2[1])**2)

position 是一个包含N_circles 点坐标的数组。

【问题讨论】:

  • 您的代码高效且易于阅读。挺好的
  • 如果您的代码有效但您想改进它,Code Review 可能是一个更好的站点。也就是说,这将有助于了解您认为改进的内容。更好的时间效率?更少的内存使用?两者都没有?
  • 谢谢 G. 安德森。我不知道代码审查网站。无论如何,我的目标是让我的代码更有效率,因为它必须循环多次。
  • @FedericoMancini 如果您想提高现有模块(如 scipy)的性能,请查看 stackoverflow.com/a/63594244/4975981 并进行性能比较。

标签: python numpy optimization euclidean-distance


【解决方案1】:

你可以使用来自 scipy 的 pdistsquareform

from scipy.spatial.distance import pdist, squareform

distances = pdist(position, metric="euclidean")
distance_matrix = squareform(distances)

【讨论】:

  • 谢谢!使用 1000 个点和 10 个周期,我的代码运行时间为 12.82 秒,而使用 pdist 和 squareform 函数则为 0.08 秒。很大的进步。
  • 我想知道这个差异是否来自库中的 C 代码与“解释的”python 代码?
  • 请注意,squareform 在几乎所有情况下都不是必需的。 “浓缩”距离矩阵通常包含所有需要的信息。
【解决方案2】:

您可以使用linalg 来计算范数。您还可以定义一个计算包含圆的超球面方程的函数

import numpy as np

def distance(w, x, b=0):
    w_norm = np.linalg.norm(w,2)
    return abs(np.dot(w,x) + b) / w_norm

【讨论】:

    【解决方案3】:

    **2 可能会使用一些“强力”子程序。使用乘法可能会更快。

    如果库中有hypot(),请使用它。

    您将保持从ij(其中i <= j)的距离。也许你也想存储[j][i]

    或者,在查找距离时,您可以使用 min(i,j) 到 'max(i,j)`。 (我不知道这是否会减少开销。)

    代码似乎计算了[i][i]。那不总是零吗?也就是说,也许你需要range(i+1, N_circles)。您可能需要也可能不需要存储0

    所有的距离每次都会改变吗?如果没有,有没有办法只重新计算那些改变的? (这是“开箱即用”思维的一个示例。可能还有其他可以使用的技巧。)

    这是另一个...

    根本不使用 SQRT。相反,保持平方距离。决定哪个“更接近”就足够了——如果这就是你所需要的。 (我在一个项目中成功使用了这种开箱即用的技巧。)

    在重新计算之前,您会查找“距离”多少次?如果 distance[]的开销)

    【讨论】: