pd.eval()仅在数据量≥10⁵行、含≥2列混合运算且启用numexpr引擎时显著更快;小数据因解析开销反而更慢,不支持函数调用、赋值语句等复杂语法。

pd.eval() 在百万行以上、多列参与的数值运算中确实更快,但小数据集反而拖慢执行——它不是万能加速器,而是特定场景下的内存与计算优化工具。
什么时候用 pd.eval() 才真快?
速度优势只在满足全部三个条件时稳定出现:
- 数据量 ≥ 10⁵ 行(实测 50 万行起差异明显)
- 表达式含 ≥2 列的混合运算,如
"a + b * c - d / e" - 未显式禁用
numexpr引擎(默认启用,且已安装)
低于 10⁴ 行时,pd.eval() 的字符串解析和编译开销会盖过计算收益;此时直接写 df['a'] + df['b'] * df['c'] 更干脆。
哪些表达式会意外报错或退化?
常见失效场景不是语法错误,而是引擎不支持导致 silently fallback 或直接抛异常:
立即学习“Python免费学习笔记(深入)”;
- 调用自定义函数(如
my_func(a))→ 报NotImplementedError: "my_func" is not supported - 用
in、is、赋值语句(=)、三元表达式(x if cond else y)→ 解析失败 - 列名含空格或特殊字符却没加反引号 →
KeyError,必须写成`col name` > 10 - 强制设
engine='python'→ 退化为标准 Python 解析,比原生 Pandas 还慢
如何确认并控制 numexpr 多线程行为?
加速依赖 numexpr 是否就位及是否合理利用 CPU 核心:
- 检查是否可用:
pd.eval("1 + 1", engine='numexpr')不报错即支持;否则运行pip install numexpr - 默认自动启用多核,但若与其他进程争资源,可手动限线程:
import numexpr as ne; ne.set_num_threads(4) - 避免在循环里反复调用同一表达式——提前算好存为新列,别重复解析
注意:numexpr 对布尔运算(如 a > 5 & b )也优化,但需用 <code>& 而非 and,且括号不能省。
eval 和 query 配合使用更省内存
pd.eval() 主攻列间计算,df.query() 主攻行过滤,二者都跳过中间 DataFrame 构建,适合链式内存敏感操作:
df = df.query('status == "active"').eval('score = (x + y) / z', inplace=False)比起先布尔索引再逐列赋值,这种写法减少至少一次完整副本生成。但要注意:query() 同样不支持 in 和自定义函数,字符串匹配得用 .str.contains() 并切换到 engine='python'——此时基本无加速,纯为语法便利。
真正容易被忽略的是:eval 加速效果高度依赖表达式“纯度”。一旦混入 .str、.dt 访问器或任何方法调用,就立刻失效。它只认裸列名和基础运算符,越接近 NumPy 式表达,越可能跑出预期速度。


















