我有一个熊猫系列,其中包含点 p 的 x 和 y 坐标,以及一个包含多个点 q的DataFrame 1 到 q n (还有 x 和 y )。然后,我计算 p 与每个 qs 之间的成对欧几里得距离。为了找到最有效的方法,我尝试了几种计算方法,其中两种方法引起了我的注意:
import pandas as pd
cs = pd.DataFrame([[10, 15], [56, 45], [33, 24]], columns=['x', 'y'])
pt = pd.Series({'x': 14, 'y': 32})
def d1(cls, pt):
return ((pt['x'] - cls['x']) ** 2 + (pt['y'] - cls['y']) ** 2) ** 0.5
def d2(cls, pt):
return ((pt - cls) ** 2).sum(axis=1) ** 0.5
第一个d1
分别减去 x 和 y 列并对其求平方,然后将它们相加,而d2
减去这两个列同时进行减法,然后使用.sum()
进行添加。
我期望d2
会更快,但是在两个函数上都使用timeit
时(运行7次,每个循环1000个),我发现d1
的速度是{{1 }(690毫秒vs 1.9秒)。
这可能是什么原因?
答案 0 :(得分:1)
d2
性能较差的原因是组织数据帧操作(索引检查对齐等)的额外开销。尽管我无法解释所有细节,但您会了解基本概念从d1和d2的配置文件图表中获取。
d1
和d2
之间的差异将随着尺寸的增加而变小:在我的计算机上,我得到的d2
/ d1
执行时间比率是2.6、2.1和1.8分别用于2、3和4维。因此,我想对于足够多的维度d2
可能比d1
更快(未经测试)。
计算欧几里得距离的最快方法是使用SciPy
中的cdist
:
from scipy.spatial import distance
def d3(cls, pt):
return pd.Series(distance.cdist(cls, [pt]).ravel())
它至少比d1
快5倍,并且实际上与尺寸数无关。
以下是我针对2、3和4维的timeit
,d1
和d2
的{{1}}输出:
d3
从原始2D情况的性能图可以看出,2D
1000 loops, best of 3: 1.37 ms per loop
100 loops, best of 3: 3.61 ms per loop
1000 loops, best of 3: 246 µs per loop
3D
100 loops, best of 3: 2.05 ms per loop
100 loops, best of 3: 4.28 ms per loop
1000 loops, best of 3: 234 µs per loop
4D
100 loops, best of 3: 2.69 ms per loop
100 loops, best of 3: 5.06 ms per loop
1000 loops, best of 3: 237 µs per loop
和d1
之间的差异也随着数据帧大小的增加而变小: