Polars 和 Pandas 有什么区别?什么时候该换成 Polars?
面试怎么回答
Pandas 大部分操作单线程、立即执行,链式操作会产生很多中间结果,内存占用是数据的好几倍,apply 加 Python 函数还是逐行跑的。Polars 用 Rust 写、基于 Arrow 列式内存,默认多线程,支持惰性执行,先建查询计划再做谓词下推和列裁剪,只读需要的数据,数据比内存大时还能流式处理;API 是表达式风格,没有行索引,更像 SQL。我会在单机处理几 GB 到几十 GB、性能成为瓶颈的 ETL 里用 Polars;探索分析和依赖 Pandas 生态的地方继续用 Pandas,两者通过 Arrow 转换开销很小;数据超过单机就上 Spark。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
做数据开发的 Python 岗,面试官越来越常问 Polars:它为什么比 Pandas 快?你会怎么选?
Pandas 慢在哪
Pandas 是数据分析的事实标准,但它有一些历史包袱:
- 大部分操作是单线程的,几十核的机器也只用一个核;
- 立即执行(Eager):每一步都马上算出完整的中间结果,链式操作会产生很多中间 DataFrame,内存占用常常是数据本身的好几倍;
- 传统上基于 NumPy,字符串等类型存成 Python 对象,又慢又占内存(Pandas 2.x 开始可以选用 Arrow 作为底层类型,有所改善)。
Polars 为什么快
Polars 用 Rust 写,底层是 Apache Arrow 列式内存格式:
- 默认多线程:分组、关联、排序等操作自动用满多核;
- 惰性执行(Lazy)+ 查询优化:用
pl.scan_parquet(...)和.lazy()时,Polars 先把整个操作链建成查询计划,做谓词下推、列裁剪等优化,只读需要的列和行,再一次执行; - 流式引擎:数据比内存大时,可以分批处理,不用一次全部装进内存;
- 表达式 API:
pl.col("amount").sum().over("user_id")这类写法可以被并行和优化,而 Pandas 里常见的apply加 Python 函数是逐行执行的,非常慢。
主要区别
| Pandas | Polars | |
|---|---|---|
| 执行方式 | 立即执行 | 立即执行和惰性执行都支持 |
| 并行 | 基本单线程 | 默认多线程 |
| 索引 | 有行索引(Index) | 没有索引,更像 SQL 表 |
| 生态 | 极其成熟,和各种库深度集成 | 较新,生态在快速追赶 |
怎么选
- 数据在几 GB 到几十 GB、单机处理、性能是瓶颈:换 Polars,往往能快好几倍,内存也省很多;
- 以探索分析为主,依赖大量 Pandas 生态(画图、统计库、老代码):继续用 Pandas,需要时用
to_pandas()/from_pandas()两边转换(基于 Arrow,开销不大); - 数据量超过单机:两个都不合适,上 Spark 或 PySpark。