对于列表中的每个点,计算到所有其他点的平均距离

时间:2015-08-19 15:11:04

标签: python numpy scipy

我有一个形状为[N,2]的numpy数组points,它包含N个点的(x,y)坐标。我想使用现有函数计算每个点到所有其他点的平均距离(我们称之为cmp_dist,我只是用作黑盒子)。

首先是"正常"的详细解决方案python来说明我想要做什么(从我的头脑中写出)

mean_dist = []
for i,(x0,y0) in enumerate(points):
    dist = [
    for j,(x1,y1) in enumerate(points):
        if i==j: continue
        dist.append(comp_dist(x0,y0,x1,y1))
    mean_dist.append(np.array(dist).mean())

我已经找到了一个更好的"使用列表推导的解决方案(假设列表推导通常更好),这似乎工作正常:

mean_dist = [np.array([cmp_dist(x0,y0,x1,y1) for j,(x1,y1) in enumerate(points) if not i==j]).mean()
                            for i,(x0,y0) in enumerate(points)]

但是,我确信在纯粹的numpy中有一个更好的解决方案,希望是一些允许使用所有其他元素对每个元素进行操作的函数。

如何在纯numpy / scipy中编写此代码?

我试图自己找一些东西,但是如果不知道如何调用这些操作(我的相应数学课程已经有一段时间了),谷歌就很难了。

修改:不是Fastest pairwise distance metric in python

的副本

该问题的作者有一个数组r,并对scipy.spatial.distance.pdist(r, 'cityblock')返回的内容感到满意(包含所有点之间距离的数组)。但是,pdist返回一个平面数组,也就是说,不清楚哪个距离属于哪个点(参见my answer)。

(虽然正如答案中所解释的那样,pdist是我最终寻找的,它并没有解决问题,因为我已经在问题中指明了它。)

1 个答案:

答案 0 :(得分:1)

基于@ ali_m对问题的评论("看看scipy.spatial.distance.pdist"),我找到了一个纯粹的" numpy / scipy解决方案:

from scipy.spatial.distance import cdist
...
fct = lambda p0,p1: great_circle_distance(p0[0],p0[1],p1[0],p1[1])
mean_dist = np.sort(cdist(points,points,fct))[:,1:].mean(1)

绝对 这确实是对我的列表理解和解决方案的改进"。

我真的不喜欢这个,但是,我必须对数组进行排序和切片以去除0.0值,这是计算相同点之间距离的结果(所以基本上是这样的'我的方法是删除我从cdist回来的矩阵的对角线条目。)

注意上述解决方案的两个方面:

  • 我使用的是cdist,而不是@al_m建议的pdist
  • 我找回了与points大小相同的数组,其中包含从每个点到所有其他点的平均距离,正如原始问题中所指定的那样。
不幸的是,

pdist只返回一个包含平面数组中所有这些平均值的数组,也就是说,平均值与它们所引用的点无关,这对于问题是必要的,因为它我和# 39;在最初的问题中描述了它。

然而,由于在实际问题中我只需要所有点的均值(我在问题中没有提到),pdist对我很好:

from scipy.spatial.distance import pdist
...
fct = lambda p0,p1: great_circle_distance(p0[0],p0[1],p1[0],p1[1])
mean_dist_overall = pdist(points,fct).mean()

虽然如果我要求手段的平均值,这肯定是肯定的答案,但是我故意要求为所有点提供一系列手段。因为我认为上述cdist解决方案仍有改进的余地,所以我不接受这个作为答案。