【问题标题】:Minimum, mean and maximum distance between points 3-D in PythonPython中3-D点之间的最小,平均和最大距离
【发布时间】:2014-03-31 13:03:51
【问题描述】:

我有一个 x,y,z 点列表。使用公式求 3-D 中两点之间的距离

import math
import numpy as np

point0 = x0, y0, z0
point1 = x1, y1, z1

dist = math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

我想写一个优化的循环并存储距离

点 = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]

dist01 = dist3d(test[0],test[1])
dist02 = dist3d(test[0],test[2])
dist03 = dist3d(test[0],test[2])
dist04 = dist3d(test[0],test[2])

dist12 = dist3d(test[1],test[2])
dist13 = dist3d(test[1],test[3])

dist23 = dist3d(test[2],test[3])

3d_l=[(dist01),(dist02),(dist03),(dist04),(dist12),(dist13),(dist23)]

3d_max =max(3d_l)
3d_min = min(3d_l)
3d_mean =  np.average(3d_l)

我写了以下函数(未优化)

def dist3d((x0, y0, z0), (x1, y1, z1)):
    return math.sqrt((x0-x1)**2+(y0-y1)**2+(z0-z1)**2)

def dist_3d(obs):
    dist_list = list()
    while len(obs) != 1:
        obs_g = [(obs[0], x) for x in obs[1:]]
        dist_list.append([dist3d(obs_g[i][0], obs_g[i][1]) for i in xrange(len(obs_g))])
        obs.pop(0)
    return dist_list

points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
print dist_3d(points)
[[4.217700795331081, 5.922339064664832, 3.554222840244929], [2.1374049685457694, 7.046453008421205], [8.107835716151763]]

【问题讨论】:

  • 你的问题是什么?
  • 伊夫感谢您的重播。我的问题是在(高效)循环中转换这些代码行
  • 是的,但你不能做什么?这样的(双)循环是微不足道的。顺便说一句,你想要平均值还是中位数?这会有很大的不同。
  • 您是否有意在计算中不包括第一个点和最后一个点之间的距离?
  • @martineau 查看更新

标签: python performance optimization computational-geometry euclidean-distance


【解决方案1】:

如果你不介意使用 scipy,这是相当简单的:

import numpy as np
import scipy.spatial.distance as distance 

points = np.array([(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0), (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)])

dist = distance.pdist(points)
print dist.max()
print dist.min()
print np.median(dist)
print np.average(dist)

【讨论】:

    【解决方案2】:

    这是一个尽可能使用内置和模块功能的通用版本。我没有安装numpy,但如果它有 3-D 或 n-D 距离函数,请使用它而不是下面的dist3D()

    实际上,numpy包含几个(其他)函数,可用于加速其中一些即时计算。如果您正在寻找更多基于它的答案,您应该通过至少修改问题的标签来表明这一点。

    import math
    import numpy as np
    
    points = [(472765.09, 6191522.78, 13.0), (472764.82, 6191524.09, 9.0),
              (472763.8, 6191525.68, 8.0), (472764.07, 6191524.39, 16.0)]
    points += [points[0]]  # dup first point to include dist from last to first
    dist3D = lambda a, b: math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2)
    dists = sorted(dist3D(points[i], points[i+1]) for i in xrange(len(points)-1))
    min_dist, max_dist = dists[0], dists[-1]
    #mean_dist = sum(dists) / len(dists)
    mean_dist = np.average(dists)
    
    print 'min_dist: {:.2f}, mean_dist: {:.2f}, max_dist: {:.2f}'.format(
        min_dist, mean_dist, max_dist)
    

    【讨论】:

      【解决方案3】:

      math.sqrt 是一个比较繁重的操作。您可以改为存储距离的平方,这足以找到最小值、中值和最大值,然后得到平方根。此外,尝试手动通过单次迭代找到最大值和最小值。

      【讨论】:

      • @YvesDaoust 我很困惑为什么它不适用于中位数。只要您保持一致,列表的中间仍然是列表的中间,无论您得到平方还是平方根。虽然我不是说这个答案是正确的,但你的评论(我假设投反对票)并不符合实际,因为他提供了一个关于简化循环的思考过程,并且它在技术上回答了这个问题(所有 -不管怎样,不好)
      • 中位数应该相同,是的,平均值不会。而且我不确定哪个OP想要。他在文本中说中位数,但在代码中使用平均值。
      • 和标题中的中间值(在他默默地修复它之前)。 @Jeff:别担心,我从来没有说过它不适用于中位数;说它不适用于“中位数”(也不适用于均值)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      • 2015-01-07
      • 1970-01-01
      • 2021-03-03
      • 2019-02-07
      • 2014-01-28
      相关资源
      最近更新 更多