跳转至

增强性能

在本教程的这一部分中,我们将研究如何 DataFrame 使用 Cython、Numba 和pandas.eval()。一般来说,使用 Cython 和 Numba 可以比使用 Cython 和 Numba 提供更大的加速,pandas.eval() 但需要更多代码。

除了遵循本教程中的步骤之外,强烈建议对增强性能感兴趣的用户安装 推荐的 pandas 依赖项。默认情况下通常不会安装这些依赖项,但如果存在,将会提高速度。

1. Cython(为 Pandas 编写 C 扩展)

对于许多用例来说,用纯 Python 和 NumPy 编写 pandas 就足够了。然而,在一些计算量大的应用程序中,可以通过将工作卸载到 Cython 来实现相当大的加速。

本教程假设您已在 Python 中进行了尽可能多的重构,例如尝试删除 for 循环并使用 NumPy 矢量化。首先在 Python 中进行优化总是值得的。

本教程将介绍对慢速计算进行 Cython 化的“典型”过程。我们使用 Cython 文档中的示例 ,但在 Pandas 的上下文中。我们最终的 cythonized 解决方案比纯 Python 解决方案快大约 100 倍。

1.1 纯 Python

我们有一个 DataFrame 需要按行应用函数进行处理。

import pandas as pd
import numpy as np

def f(x: float) -> float:
    return x * (x - 1)

def integrate_f(a: float, b: float, N: int) -> float:
    s = 0
    dx = (b - a) / N

    for i in range(N):
        s += f(a + i * dx)
    return s * dx


df = pd.DataFrame(
    {
        "a": np.random.randn(1000),
        "b": np.random.randn(1000),
        "N": np.random.randint(100, 1000, (1000)),
        "x": "x",
    }
)

我们通过使用 DataFrame.apply()(逐行)来实现我们的结果:

IPython
%timeit df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
74.9 ms +- 728 us per loop (mean +- std. dev. of 7 runs, 10 loops each)

让我们使用 prun ipython 魔术函数来看看这个操作期间花费的时间在哪里:

Linux下运行
%prun -l 4 df.apply(lambda x: integrate_f(x["a"], x["b"], x["N"]), axis=1)
605956 function calls (605938 primitive calls) in 0.167 seconds

到目前为止,大部分时间都花在 integrate_f,f因此我们将集中精力对这两个函数进行 cython 化。

1.2 普通 Cython

首先,我们需要将 Cython 魔术函数导入 IPython:

无法编译
%load_ext Cython

%%cython
def f_plain(x: float) -> float:
    return x * (x - 1)

def integrate_f_typed(a: float, b: float, N: int) -> float:
    s = 0
    dx = (b - a) / N

    for i in range(N):
        s += f_plain(a + i * dx)
    return s * dx

%timeit df.apply(lambda x: integrate_f_typed(x["a"], x["b"], x["N"]), axis=1)
46.6 ms +- 466 us per loop (mean +- std. dev. of 7 runs, 10 loops each)

与纯 Python 方法相比,这将性能提高了三分之一。

1.3 声明 C 类型

1.4 使用 ndarray

1.5 禁用编译器指令

2. Numba(JIT 编译)

2.1 Pandas Numba 引擎

2.2 自定义函数示例

2.3 注意事项

3. 进行表达式评估 eval

3.1 支持的语法

3.2 pandas.eval 解析器

3.3 eval性能比较

3.4 表达式求值限制 numexpr