【问题标题】:Get closest coordinate in 2D array获取二维数组中最近的坐标
【发布时间】:2019-04-14 21:43:24
【问题描述】:
coordinates = [(-225.0, -299.5), (-150.0, 75.5), (0.0, 0.0), (225.0, 300.5)]

xy = (-222.4, -204.5)

将给定值 xy 与二维坐标列表进行比较并返回最近坐标的索引号的最佳方法是什么?

在本例中,xy 将与坐标列表进行比较,从而返回最接近的坐标(-225.0、-299.5),或者更理想的是索引号 0。

我尝试使用 itertools 或 numpy 研究一种方法,但似乎无法理解如何在我的示例中获得我想要的结果。

【问题讨论】:

    标签: python list multidimensional-array coordinates itertools


    【解决方案1】:

    使用 scipy.spatial.KDTree:

    from scipy import spatial
    import numpy as np
    coordinates = [(-225.0, -299.5), (-150.0, 75.5), (0.0, 0.0), (225.0, 300.5)]
    x = [(-222.4, -204.5)]
    distance,index = spatial.KDTree(coordinates).query(x)
    print(distance)
    print(index)
    

    kd-tree 方法是 O(N*log(N)) 并且比 Brute Force 方法快得多,Brute Force 方法需要 O(N**2) 时间来获得足够大的 N。

    【讨论】:

      【解决方案2】:

      您的问题相当于:如何使用自定义方法对 Python 列表进行排序以定义排序键。这可以在原始 python 中完成,而无需使用外部库。

      使用 python 的 sorted() 函数时,您可以将 lambda 传递给 key 参数以对特定键进行排序。

      从那里您只需将键定义为您自己的距离计算方法(这里使用点之间的距离):

      from math import *
      coordinates = [(-225.0, -299.5), (-150.0, 75.5), (0.0, 0.0), (225.0, 300.5)]
      xy = (-222.4, -204.5)
      results = sorted(coordinates, key= lambda v: sqrt(pow((v[0] - xy[0]), 2) + pow((v[1] - xy[1]), 2)))
      # Output : [(-225.0, -299.5), (-150.0, 75.5), (0.0, 0.0), (225.0, 300.5)]
      

      如果你想要更近的点,你可以从那里获取列表的第一个元素,等等。如果你仍然想要外部模块,我认为你可以使用一些第三方函数,例如 from scipy.spatial import distance 作为关键参数排序。

      【讨论】:

      • 使用自定义键函数对列表进行排序涉及比简单地找到传递给该函数时产生最小值的列表元素更多的处理 - 所以,不,问题不等同于那个.如果是这样,我建议使用math.hypot() 函数,因为它比你这样做的方式更快。看到这个comment关于那个。
      【解决方案3】:

      您可以将min 与适当的key 函数一起使用。比如以下几行:

      coordinates = [(-225.0, -299.5), (-150.0, 75.5), (0.0, 0.0), (225.0, 300.5)]
      xy = (-222.4, -204.5)
      
      dist = lambda x, y: (x[0]-y[0])**2 + (x[1]-y[1])**2
      min(coordinates, key=lambda co: dist(co, xy))
      # (-225.0, -299.5)
      

      【讨论】:

      • 我建议改用math.hypot()——它可能更快。
      • @martineau 我不太明白到原点的距离在这种一般距离情况下有何帮助。
      • min(coordinates, key=lambda p: math.hypot(p[0]-xy[0], p[1]-xy[1]))
      • @martineau 所以你添加了一个额外的函数调用并且仍然在纯 Python 中进行计算?不太有说服力....
      • 执行时间是唯一确定的方法。这样做,我发现对于更多的点,你的方式比在 Python 3.7.1 中使用hypot() 慢约 19%。这是用于确定这一点的benchmark(结果在最后)。
      【解决方案4】:

      您可以简单地创建一个函数来遍历坐标列表并保留两点之间距离最小的那个的索引(使用勾股定理)。

      但是,如果您需要外部模块快速提供的东西而不是自己编写,我不知道我已经使用过的库已经具有该功能,所以我在这里没有帮助。

      【讨论】:

      • 我想过这个,但是如果我的列表中有负坐标和正坐标,勾股定理会不会不起作用?例如如果坐标 = [(-255.0,-255.0), (255.0,255.0)] -> 它不知道哪个坐标更接近?
      • @Ben 负坐标没有问题,毕达哥拉斯仍然会注意正确的距离。如果确实两组坐标具有相同的距离,您只需要决定一个决胜局。
      • 如果你有负坐标和正坐标,它肯定会起作用,公式不关心你有正坐标还是负坐标。 link 如果一个特定点与其他两个点的距离相同,它将采用列表中出现的第一个点的索引。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-23
      • 2021-08-19
      • 2015-11-16
      • 2012-02-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多