【问题标题】:python - given two tuples lists find the closest tuple between them (distpython - 给定两个元组列表找到它们之间最近的元组(dist
【发布时间】:2018-04-13 07:29:10
【问题描述】:

我有两个带有元组(坐标)的列表,例如:

some_pt1 = [(10.76,2.9),(3.24,4.28),(7.98,1.98),(3.21,9.87)]
some_pt2 = [(11.87,6.87), (67.87,8.88), (44.44, 6.78), (9.81, 1.09), (6.91, 0.56), (8.76, 8.97), (8.21, 71.66)]
  • 元组中的每个值都是一个平面
  • 列表长度不同

我如何找到两个列表之间的两个最近点。我不知道如何,也许可以使用距离来做到这一点。我希望有一种更有效的方法来做到这一点,因为我需要这个函数尽可能快地工作(它是更大的一部分)。

【问题讨论】:

  • 是否要求这两个点来自 both 列表,或者您是否还包括与同一列表中的点的距离?
  • “最接近”的指标是什么?欧几里得?
  • 要求每个点来自不同的列表
  • 欧几里得...

标签: python python-2.7 listview tuples coordinates


【解决方案1】:

或者,通过参考 Tim Seed 的代码。这个可以用。

from scipy.spatial import distance
some_pt1 = [(10.76,2.9),(3.24,4.28),(7.98,1.98),(3.21,9.87)]
some_pt2 = [(11.87,6.87), (67.87,8.88), (44.44, 6.78), (9.81, 1.09), (6.91, 0.56), (8.76, 8.97), (8.21, 71.66)]

empthy_dict = {}
for i in range(len(some_pt1)):
    for j in range(len(some_pt2)):
        dist = distance.euclidean(some_pt1[i],some_pt2[j])
        empthy_dict[dist] = [some_pt1[i],some_pt2[j]]

shortest = sorted(empthy_dict.keys())[0]
points = empthy_dict[shortest]
print('Shortest distance is ' ,shortest,' and points are ' ,points)

【讨论】:

    【解决方案2】:

    这个怎么样

    from pprint import pprint
    
    some_pt1 = [(10.76,2.9),(3.24,4.28),(7.98,1.98),(3.21,9.87)]
    some_pt2 = [(11.87,6.87), (67.87,8.88), (44.44, 6.78), (9.81, 1.09), (6.91, 0.56), (8.76, 8.97), (8.21, 71.66)]
    
    
    distance = {}
    for x in some_pt1:
        for y in some_pt2:
            dist =abs(abs(x[0])-abs(y[0]))+abs(abs(x[1])-abs(y[1]))
            distance[dist]=[x,y]
    
    shortest =sorted(distance.keys())[0]
    print("Min Distance is {} Objects are  {} {} ".format(shortest, distance[shortest][0],distance[shortest][0]))
    

    【讨论】:

    • 这是(几乎,太多abs)曼哈顿指标,这是错误的:)
    【解决方案3】:

    欧几里得距离:

    >>> some_pt1 = [(10.76,2.9),(3.24,4.28),(7.98,1.98),(3.21,9.87)]
    >>> some_pt2 = [(11.87,6.87), (67.87,8.88), (44.44, 6.78), (9.81, 1.09), (6.91, 0.56), (8.76, 8.97), (8.21, 71.66)]
    >>> 
    >>> def dist_sq(p1_p2):
    ...     p1, p2 = p1_p2
    ...     return sum(x*y for x,y in zip(p1, p2))
    ... 
    >>> 
    >>> min(((p1, p2) for p1 in some_pt1 for p2 in some_pt2), key=dist_sq)
    ((3.24, 4.28), (6.91, 0.56))
    

    它的运行时间为 O(n*m)(其中 n, m 是列表的长度)。由于您需要查看所有配对,因此没有比这更好的了。

    注意,比较距离的平方就足够了,不需要计算根。

    【讨论】:

    • 谢谢,看起来它可以很好地完成这项工作,但它让我问:有没有其他方法可以更有效地做到这一点,然后通过检查每一个导致我将拥有的真实列表会很长,并且可能有非常远的点。
    • @eranhalperin 不,你不能降低算法的复杂性。您可以使用 numpy 和 Jorge Rodriguez Molinuevo 提到的其他技术使其更快,但您需要比较每一对。
    • 好的,那么我如何使用 numpy(例如)使其工作得更快
    【解决方案4】:

    在任何情况下,您都需要进行所有可能的组合,有一些算法可以帮助您以最佳顺序完成或避免重复距离。如果你想快速完成,你应该使用一个特殊的库来帮助编译或预编译数组,这可以通过NumbaCython 来完成。其他库(例如 scipy)具有特殊模块,例如 scipy.spatial.distance。更多疑惑看这个帖子similar cuestion

    例子:

    import scipy.spatial.distance as sd
    import numpy as np
    some_pt1 = [(10.76,2.9),(3.24,4.28),(7.98,1.98),(3.21,9.87)]
    some_pt2 = [(11.87,6.87), (67.87,8.88), (44.44, 6.78), (9.81, 1.09), (6.91, 0.56), (8.76, 8.97), (8.21, 71.66)]
    np.unravel_index(np.argmin(sd.cdist(some_pt1, some_pt2)), (len(some_pt1), len(some_pt2)))
    

    结果:(2, 4)

    此代码将返回第一个列表和第二个列表中的位置。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-23
      • 1970-01-01
      • 1970-01-01
      • 2018-06-12
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多