You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Polars表达式实现列的eval()应用,替代逐行映射?

高效实现Polars批量表达式求值

问题分析

你当前用map_elements配合eval逐行处理表达式的方式,在百万级数据量下效率极低——因为map_elements本质是Python层面的逐行循环,加上eval的动态解析开销,会导致严重的性能瓶颈。核心优化思路是利用Polars的向量化操作,彻底避免逐行Python调用。

解决方案

由于foo()、bar()、baz()是无参数函数,它们的结果是固定值,不需要每行重复计算。我们可以先预计算函数结果,再通过字符串匹配直接映射为Polars原生布尔表达式,实现批量向量化处理:

import polars

def foo():
    return 1 + 1

def bar():
    return 1 + 1

def baz():
    return 2 + 2

# 预计算所有函数的固定结果,仅执行一次
val_foo = foo()
val_bar = bar()
val_baz = baz()

exprs = 1_000_000 * [
    "foo() == bar()",
    "bar() == baz()",
    "foo() == baz()",
    "foo() > bar()",
    "bar() < baz()",
    "foo() != baz()",
]

df = polars.DataFrame({"exprs": exprs})

# 建立表达式字符串到Polars布尔表达式的映射
expr_mapping = {
    "foo() == bar()": polars.lit(val_foo) == val_bar,
    "bar() == baz()": polars.lit(val_bar) == val_baz,
    "foo() == baz()": polars.lit(val_foo) == val_baz,
    "foo() > bar()": polars.lit(val_foo) > val_bar,
    "bar() < baz()": polars.lit(val_bar) < val_baz,
    "foo() != baz()": polars.lit(val_foo) != val_baz,
}

# 用replace实现向量化替换,直接生成布尔结果列
result_df = df.with_columns(
    result=polars.col("exprs").replace(expr_mapping, default=False)
)

print(result_df)

优化原理

  1. 预计算函数结果:哪怕函数逻辑复杂,也只需要执行一次,避免了百万次重复调用的开销。
  2. 向量化替换:replace是Polars的原生向量化操作,底层由Rust实现,处理百万级数据的速度远快于Python层面的逐行循环。
  3. 批量匹配:利用表达式字符串的重复性,一次性完成相同模式的批量转换,进一步压缩计算开销。

扩展场景

如果你的函数需要依赖DataFrame中的其他列(带参数),可以通过Polars的when/then分支表达式,或者注册自定义Polars表达式构建器(pl.register_expr_builder)来实现,但核心思路依然是尽量用Polars原生表达式,避免逐行Python循环。

内容的提问来源于stack exchange,提问作者FISR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 21:54:55