如何高效地计算pandas数据框中每一行到单个点的距离?

18

我有一个观点

point = np.array([0.07852388, 0.60007135, 0.92925712, 0.62700219, 0.16943809,
       0.34235233])

还有一个pandas数据框

           a           b           c           d           e           f
0   0.025641    0.554686    0.988809    0.176905    0.050028    0.333333
1   0.027151    0.520914    0.985590    0.409572    0.163980    0.424242
2   0.028788    0.478810    0.970480    0.288557    0.095053    0.939394
3   0.018692    0.450573    0.985910    0.178048    0.118399    0.484848
4   0.023256    0.787253    0.865287    0.217591    0.205670    0.303030

我想计算pandas数据框中每一行到特定点的距离。

我尝试过

import numpy as np
d_all = list()
for index, row in df_scaled[cols_list].iterrows():
        d = np.linalg.norm(centroid-np.array(list(row[cols_list])))
        d_all += [d]
df_scaled['distance_cluster'] = d_all

尽管我想要计算与其他点之间的距离,但我的解决方案速度非常慢。

有没有一种更高效的方法来进行计算?

4个回答

12

另一个选择是使用cdist,它速度稍快:

from scipy.spatial.distance import cdist
cdist(point[None,], df.values)

输出:

array([[0.47468985, 0.25707985, 0.70385676, 0.5035961 , 0.46115096]])

一些与10万行的比较:

%%timeit -n 10
cdist([point], df.values)
645 µs ± 36.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit -n 10
np.linalg.norm(df.to_numpy() - point, axis=1)
5.16 ms ± 227 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit -n 10
df.sub(point, axis=1).pow(2).sum(axis=1).pow(.5)
16.8 ms ± 444 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

这是一个不错的选择,但需要引入一个额外的包/导入。一般来说没有任何问题,但有些人可能会反对安装新库。此外,根据您的数据,结果可能因人而异。 - cs95

11

您可以使用以下公式计算向量化欧几里得距离(L2范数)

sqrt((a1 - b1)2 + (a2 - b2)2 + ...)

df.sub(point, axis=1).pow(2).sum(axis=1).pow(.5)

0    0.474690
1    0.257080
2    0.703857
3    0.503596
4    0.461151
dtype: float64
与您当前的代码输出相同。
或者,使用 linalg.norm:
np.linalg.norm(df.to_numpy() - point, axis=1)
# array([0.47468985, 0.25707985, 0.70385676, 0.5035961 , 0.46115096])

4

让我们使用scipy

from scipy.spatial import distance
ary = distance.cdist(df.values, np.array([point]), metric='euclidean')
ary
Out[57]: 
array([[0.47468985],
       [0.25707985],
       [0.70385676],
       [0.5035961 ],
       [0.46115096]])

2
有点晚了,但您可以将np.linalg.norm函数应用于数据框架。请点击apply
df['distance_cluster'] = df.apply(lambda x : np.linalg.norm(x-point),1)

输出:

#print(df['distance_cluster'])

0    0.474690
1    0.257080
2    0.703857
3    0.503596
4    0.461151
dtype: float64

然而,与numpy解决方案相比,它会慢得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接