python - 为什么在计算欧几里德距离时,按列计算比 Pandas 中整个 DataFrame 的计算更快

标签 python pandas performance dataframe

我有一个 pandas 系列,其中包含一个点 pxy 坐标,以及一个包含多个点 q 的 DataFrame 1qn(还有 xy)。然后我计算 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,分别对 xy 列进行减法和平方,然后将它们相加,而 d2 同时减去两列进行减法,然后使用 .sum() 将它们相加。

我预计 d2 会更快,但是当在两个函数上使用 timeit 时(7 次运行,每个 1000 次循环)我发现 d1d2 快近三倍(690 毫秒对 1.9 秒)。

这可能是什么原因?

最佳答案

d2 性能较差的原因是组织数据帧操作的额外开销(索引检查对齐等)虽然我无法解释你会得到的每一个细节d1 的剖面图的基本概念和 d2 .

d1d2 之间的差异会随着维度的增加而变小:在我的机器上我得到一个 d2/d1 2、3 和 4 维的执行时间比率分别为 2.6、2.1 和 1.8。所以我猜对于足够多的维度,d2 可能比 d1 更快(未测试)。

计算欧氏距离的最快方法是使用 cdist来自 SciPy:

from scipy.spatial import distance

def d3(cls, pt):
    return pd.Series(distance.cdist(cls, [pt]).ravel())

它至少比 d1 快 5 倍,而且实际上不依赖于维数。 以下是我对 d1d2d3 的 2、3 和 4 维度的 timeit 输出:

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

从原始 2D 案例的性能图中可以看出,d1d2 之间的差异也随着数据帧大小的增加而变小:

enter image description here

关于python - 为什么在计算欧几里德距离时,按列计算比 Pandas 中整个 DataFrame 的计算更快,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57788654/

相关文章:

python - 计算数据帧切片的统计信息

python - 删除 pandas 数据框中少于 6 个月的重叠周期

javascript - 显示更多按钮不适用于我的 table

python - 如何去除可能出现在字符串列值开头或结尾的货币字符?

python - Neomodel 密码查询缺少位置参数

python - lxml解析器吃掉所有内存

python - 多处理:通过多个进程运行数组?

python - 使用基准年计算指数

javascript - MongoDB 确定一条记录是否会通过 findOne

ruby-on-rails - 一旦我的应用程序爬升到 > 1000 个对象,Sunspot-Solr 就会慢下来 [包括 Solr 日志]