Python 如何在两个具有最小距离的点列表中高效地找到点对?
pointListA和pointListB的长度几乎为5000或更多。我的任务是为pointListA中的每个点找到pointListB中的点,以便这两个点之间的距离最小。 我的问题是找到一个有效的方法来完成这项任务。我已经尝试了一些方法,比如遍历两个列表,但是速度太慢了。那么,有什么建议给我吗 编辑1: 我很抱歉刚才在标题中对我的描述。现在我将其修改为“如何有效地在两个具有最小距离的点列表中查找点对” 事实上,我想要这样的结果Python 如何在两个具有最小距离的点列表中高效地找到点对?,python,math,Python,Math,pointListA和pointListB的长度几乎为5000或更多。我的任务是为pointListA中的每个点找到pointListB中的点,以便这两个点之间的距离最小。 我的问题是找到一个有效的方法来完成这项任务。我已经尝试了一些方法,比如遍历两个列表,但是速度太慢了。那么,有什么建议给我吗 编辑1: 我很抱歉刚才在标题中对我的描述。现在我将其修改为“如何有效地在两个具有最小距离的点列表中查找点对” 事实上,我想要这样的结果 pointListA = [(13,45),(33,78),...
pointListA = [(13,45),(33,78),...,(360,240)]
pointListB = [(20,36),(47,32),...,(265,322)]
假设您希望从具有相同索引的每个列表中获取两个点,您可以
zip
两个列表。如果您指的是从A和B中选择的任意点之间的最小距离,则应使用itertools.product
:
minDistansceList = [((13,45),(a point in pointListB)),((33,78),(a point in pointListB)).....((360,240),(a point in pointListB))]
更新后:
>>> from itertools import starmap, product
>>> from math import sqrt, pow
>>> def distance(p1, p2):
... return sqrt(pow(p2[1] - p1[1], 2) + pow(p2[0] - p1[0], 2))
>>> pointListA = [(13,45), (33,78), (360,240)]
>>> pointListB = [(20,36), (47,32), (265,322)]
>>> min(starmap(distance, product(pointListA, pointListB)))
11.40175425099138
假设您希望从具有相同索引的每个列表中获取两个点,您可以
zip
两个列表。如果您指的是从A和B中选择的任意点之间的最小距离,则应使用itertools.product
:
minDistansceList = [((13,45),(a point in pointListB)),((33,78),(a point in pointListB)).....((360,240),(a point in pointListB))]
更新后:
>>> from itertools import starmap, product
>>> from math import sqrt, pow
>>> def distance(p1, p2):
... return sqrt(pow(p2[1] - p1[1], 2) + pow(p2[0] - p1[0], 2))
>>> pointListA = [(13,45), (33,78), (360,240)]
>>> pointListB = [(20,36), (47,32), (265,322)]
>>> min(starmap(distance, product(pointListA, pointListB)))
11.40175425099138
尝试使用
str(pointListA/pointlistB)%str(pointListA/pointlistB)
尝试使用str(pointListA/pointlistB)%str(pointListA/pointlistB)
您可以使用元组作为由距离填充的字典的键,然后从中提取最小值
>>> sorted(product(pointListA, pointListB), key=lambda t: distance(t[0], t[1]))
>>> [((13, 45), (20, 36)), ((13, 45), (47, 32)), ((33, 78), (20, 36)), ...]
可以将元组用作由距离填充的字典的键,然后从中提取最小值
>>> sorted(product(pointListA, pointListB), key=lambda t: distance(t[0], t[1]))
>>> [((13, 45), (20, 36)), ((13, 45), (47, 32)), ((33, 78), (20, 36)), ...]
我不确定,但您可以通过从使用结果得到的矩阵中提取结果,从而有效地做到这一点:
pointListA = ((0,1),(1,2),(3,4),(2,2))
pointListB = ((0,1),(1,2),(3,4),(2,2))
dists = {}
for p0 in pointListA:
dists[p0] = {}
for p1 in pointListB:
d = 0
for k in [0,1]:
d += (p0[k]-p1[k])**2
dists[p0][p1] = d**0.5
minDistPairs = tuple([(k,min(dists[k], key=dists[k].get)) for k in dists])
print minDistPairs
我们采用对角线的原因是因为cdist
返回从a中的每个点到B中的每个点的距离矩阵。我关心的是,这将生成AxB中间结果以提取len(a)结果的向量。但它将在NumPy的低级(编译的二进制)代码中进行矢量化操作,并可能利用CPU自己的矢量指令集扩展(例如x86上的SSE)
我怀疑有某种方法可以消除额外的计算,但我知道的NumPy不够。我不确定,但您可以从使用结果得到的矩阵中提取,从而有效地实现这一点:
pointListA = ((0,1),(1,2),(3,4),(2,2))
pointListB = ((0,1),(1,2),(3,4),(2,2))
dists = {}
for p0 in pointListA:
dists[p0] = {}
for p1 in pointListB:
d = 0
for k in [0,1]:
d += (p0[k]-p1[k])**2
dists[p0][p1] = d**0.5
minDistPairs = tuple([(k,min(dists[k], key=dists[k].get)) for k in dists])
print minDistPairs
我们采用对角线的原因是因为cdist
返回从a中的每个点到B中的每个点的距离矩阵。我关心的是,这将生成AxB中间结果以提取len(a)结果的向量。但它将在NumPy的低级(编译的二进制)代码中进行矢量化操作,并可能利用CPU自己的矢量指令集扩展(例如x86上的SSE)
我怀疑有某种方法可以消除额外的计算,但我知道的NumPy不够。作为一种优化,如果在距离0处找到一个点,您可以利用找到最近点的事实,并利用使平方距离最小的点使距离最小的事实:
#!/bin/python
import numpy as np
from scip.spatial.distance import cdist
pointListB = [(20,36),(47,32),(265,322)]
pointListA = [(13,45),(33,78),(360,240)]
A = np.array(pointListA)
B = np.array(pointListB)
distances = np.diagonal(cdist(A, B, 'euclidean'))
# Minimum distance:
min_dist = np.min(distances)
然后
在我2岁的笔记本电脑上大约需要18秒作为一种优化,如果在距离0处找到一个点,您可以利用找到最近点这一事实,并利用一个使距离平方最小的点:
#!/bin/python
import numpy as np
from scip.spatial.distance import cdist
pointListB = [(20,36),(47,32),(265,322)]
pointListA = [(13,45),(33,78),(360,240)]
A = np.array(pointListA)
B = np.array(pointListB)
distances = np.diagonal(cdist(A, B, 'euclidean'))
# Minimum distance:
min_dist = np.min(distances)
然后
在我2岁的笔记本电脑上花了大约18秒我对刚才标题中的描述感到抱歉。现在,我更新了我的问题。那么,关于这个问题有什么想法吗?这不是我的操作,我会给你一个答案:-)是的,我忘了用min({},{}.get)来获取min键。。。关于这一点,我应该测试得更好…还有一个问题,两个列表的长度超过5000,我只是在我的电脑上用intel i7 core测试代码,它需要23秒来完成计算,有没有办法使它更有效?我很抱歉刚才在标题中描述了。现在,我更新了我的问题。所以,你知道这个问题吗?这不是我的职责,我会给你一个答案:-)是的,我忘了用min({},{}.get)来获取min键。。。关于这一点,我应该测试得更好…还有一个问题,两个列表的长度超过5000,我只是在我的电脑上用英特尔i7内核测试代码,需要23秒才能完成计算,有没有办法让它更有效?你不需要参加sqrt,因为你是在最小化是的,在我认为OP想要看到最小距离之前,不是按最小距离排列的配对列表。我是指从A和B中选择的任何点之间的最小距离。你不需要进行sqrt,因为你是最小的。是的,在我认为OP想要看到最小距离之前,不是按最小距离排序的配对列表。我的意思是从A和位中选择的任何点之间的最小距离在我的计算机上大约需要8秒,这是perfect@Elivis这个问题称为最近邻搜索。以预处理
pointListB
为代价,您应该能够将其归结为O(n*log(n))
而不是O(n^2)
。预处理看起来很重要,可能不值得,但如果这被证明是一个瓶颈,你可能需要研究更复杂的算法(比如使用k-d树的算法)。在我的计算机上大约需要8秒钟,这是很重要的perfect@Elivis这个问题称为最近邻搜索。以预处理pointListB
为代价,您应该能够将其归结为O(n*log(n))
而不是O(n^2)
。预处理似乎很重要,可能不值得,但如果这被证明是一个瓶颈,您可能需要研究更复杂的算法(例如使用