df.query()比布尔索引快2–5倍,因其通过numexpr引擎执行字符串条件,跳过构建中间布尔数组;pd.eval()仅返回计算结果,适用于生成复杂条件或中间列计算。

对 10 万行以上的 DataFrame 做多列复合条件过滤时,df.query() 和 pd.eval() 能比普通布尔索引快 2–5 倍,前提是表达式写法正确、避免触发 Python 解释器回退。
query() 为什么比布尔索引快?
query() 把字符串条件交给 numexpr 引擎执行,跳过 Pandas 构建中间布尔数组的过程;而 df[(df.A > df.B) & (df.C == 'x')] 会先算出两个 bool Series,再用 & 合并——这一步产生临时对象,内存和 CPU 开销都大。
- 必须用
and/or/not(不是&/|/~),括号可省略:df.query("A > B and C == 'x'") - 支持外部变量,用
@前缀:threshold = 100; df.query("price > @threshold") - 列名含空格或特殊字符时,用反引号包裹:
df.query("`user id` > 1000") - 不支持方法调用(如
df.col.str.contains('abc')不能直接写进query)
pd.eval() 的适用场景和限制
pd.eval() 不返回数据,只返回计算结果(标量、Series 或 bool 数组),适合做「条件生成」或「中间列计算」。它比原生 Python 表达式快,但比 query() 少一层语法糖封装。
- 用于构造复杂布尔条件再喂给
df[...]:mask = pd.eval("df.A > df.B & df.C - 表达式里不能出现
df.前缀(这是常见错误):pd.eval("A > B & C 才对,且所有变量需在当前作用域可见 - 支持
numexpr特有函数如where、sin,但不支持 Pandas 方法链 - 当表达式含大量标量运算(如
A * 0.8 + B / 2.5),pd.eval()比直接写df.A * 0.8 + df.B / 2.5略快,但差距不如query()明显
哪些情况反而更慢?
小数据量(query() 和 pd.eval() 回退到 Python 解释器执行,此时比原生写法还慢。
立即学习“Python免费学习笔记(深入)”;
- 写了
.str.contains()或.dt.year这类方法:numexpr 不识别,直接报NotImplementedError或静默降级 - 用了未定义变量或拼错列名,错误信息模糊(如
KeyError: 'name'),调试成本高于普通布尔索引 - 启用了
engine='python'(默认是'numexpr'),等于白用:df.query("A > B", engine='python') - 字符串条件里混用单双引号导致解析失败,例如
df.query("name == "John"")—— 必须统一引号或用转义
真正起效的前提是:数据够大、条件纯算术/比较、不碰 Pandas 方法链。别为了“用高级功能”而用,先 %timeit 对比三秒内的实际耗时。


















