如何有效地从单个点计算熊猫数据框中每一行的距离?

qua*_*ant 18 python pandas

我有一点

point = np.array([0.07852388, 0.60007135, 0.92925712, 0.62700219, 0.16943809,
       0.34235233])
Run Code Online (Sandbox Code Playgroud)

还有一个熊猫数据框

           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
Run Code Online (Sandbox Code Playgroud)

我想计算熊猫数据框中每一行到那个特定点的距离

我试过

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
Run Code Online (Sandbox Code Playgroud)

不过,我的解决方案真的很慢(考虑到我也想计算与其他点的距离。

有没有办法更有效地进行计算?

cs9*_*s95 10

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

sqrt((a 1 - b 1 ) 2 + (a 2 - b 2 ) 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
Run Code Online (Sandbox Code Playgroud)

它提供与您当前代码相同的输出。


或者,使用linalg.norm:

np.linalg.norm(df.to_numpy() - point, axis=1)
# array([0.47468985, 0.25707985, 0.70385676, 0.5035961 , 0.46115096])
Run Code Online (Sandbox Code Playgroud)


Qua*_*ang 10

另一种选择是使用cdist,它有点快:

from scipy.spatial.distance import cdist
cdist(point[None,], df.values)
Run Code Online (Sandbox Code Playgroud)

输出:

array([[0.47468985, 0.25707985, 0.70385676, 0.5035961 , 0.46115096]])
Run Code Online (Sandbox Code Playgroud)

与 100k 行的一些比较:

%%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)
Run Code Online (Sandbox Code Playgroud)