我有一个形状为[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
是我最终寻找的,它并没有解决问题,因为我已经在问题中指明了它。)
答案 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
解决方案仍有改进的余地,所以我不接受这个作为答案。