【问题标题】:Find the Nearest Neighbor To A Given Point in a List of Points in Python在 Python 中的点列表中找到给定点的最近邻居
【发布时间】:2019-12-25 13:07:34
【问题描述】:

我正在尝试找到与 2D(X, Y) 网格中的点最近的邻居。

目前我选择一个随机点:

(x1, y1) = choice(self.rooms)

如何在self.rooms(x1, y1) 的列表中找到最近的邻居?

我的列表是由程序生成的 (x, y) 坐标列表,包含大约 30 个项目。

print(self.rooms)

返回: [(13, 5), (6, 30), ...] 为简洁起见被截断

我想我可以使用 scikit-learn 的 KDTree,但我不知道如何实现它。我试过寻找答案,但我似乎能找到的只是如何使用 KDTree 返回列表中最近的两个点。

【问题讨论】:

  • 参考here
  • 什么是self.rooms
  • 请展示您正在使用的内容和尝试过的内容的最小示例。

标签: python


【解决方案1】:

最简单的方法是对数据库中的所有点使用 O(N) 检查。

import math
def get_dist(a,b):
  return math.sqrt((a[0]-b[0])**2 + (a[1]-b[1])**2)

p = choice(self.rooms) #your point
n = len(self.rooms)
dist = math.inf #(infinity)
for i in range(n):
   d = get_dist(p,self.rooms[i])
   if d<dist and d!=0: # to avoid the same point
      dist =d
      np= self.rooms[i]
print(np) # nearest point

是否使用此算法取决于您拥有多少数据,因为它适用于小型数据集(样本在问题中会很好)。

如果您想要一个简短的实现,功能方法会更好,就像另一个答案:

p = choice(self.rooms) #point to compare
dists= [(i,get_dist(p,i)) for i in self.rooms if get_dist(p,i)!=0] #all distances
min_dist = min(dists) #minimum distance
np = list([self.rooms[i] for i,j in dists if j==min_dist])[0] # Corresponding point. 


【讨论】:

  • 即使有大量数据,预处理点(例如,构建 k-d 树)的成本也高于重复的线性搜索,除非您计划进行大量类似的查询。跨度>
  • 我的数据集只有大约 30 个 (x, y) 元组。更新问题以反映,我会试试这个,谢谢。
  • 使用上述方法我得到d = dist(n1, i) TypeError: 'int' object is not callable 我认为这是由于从列表中解包元组的问题。
  • 我意识到我需要使用self.dist 而不是dist,但现在我得到了d = self.dist(n1, i) TypeError: dist() takes 2 positional arguments but 3 were givenprint(n1, i) 返回(149, 55) 0
  • 我已经编辑了代码,你需要检查第i^th点的距离,即self.rooms[i],i是一个整数。你通过调用 self.dist 给出了 3 个参数,问题是 dist 既被定义为函数又被定义为参数,我的错。我也编辑过
【解决方案2】:

由于点的数量很少,简单地遍历列表就可以了;不需要更高级的数据结构。

使用min 函数是很自然的,它支持一个key 参数来说明如何比较元素。我们还可以通过不取距离的平方根来稍微提高效率;如果我们按平方距离而不是距离进行比较,则最近点是相同的。

def closest_point(points, target):
    tx, ty = target
    return min(points, key=lambda p: (p[0] - tx)**2 + (p[1] - ty)**2)

例子:

>>> closest_point([(1, 2), (3, 4), (5, 6), (7, 8)], (4, 2))
(3, 4)

【讨论】:

  • 使用这个返回相同的点。 (155, 68), (155, 68) 我调用的点在我引用的列表中。我将不得不寻找一种方法来搜索除自身以外的最近点。
  • 你可以做closest_point(set(self.rooms) - { (x1, y1) }, (x1, y1))
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-08
  • 2019-09-02
  • 2020-06-15
  • 2018-08-28
  • 2018-06-26
相关资源
最近更新 更多