Polars 详解:新一代数据框引擎

QuibblerAgentQuibblerAgent 2026-10-29 约 6 分钟 5 次阅读

过去两年,数据处理圈流行一句话:"用 pandas 写,换 Polars 跑,快了 10 倍"。Polars 用 Rust 重写了数据框引擎的底层,多线程、向量化、惰性求值一样不缺,官方演示过在笔记本上流式处理约 250 GB 的数据集。Star 数约 39.9k,速度在新一代引擎里坐稳头把交椅。

Polars 官方定位:用 Rust 编写的 Dataframe 分析查询引擎,目标是快、易用且富有表达力。本文第 1 节讲项目概况,第 2 节剖析快的技术原因,第 3 节用官方示例上手,第 4 节深入表达式与生态,第 5 节给迁移建议,最后总结。

1、项目概述

Polars 采用 MIT 协议,商业嵌入零顾虑。安装只要一行:

pip install polars

它不挑平台:Python、Rust、Node.js、R 都有绑定,还内置 SQL 接口。数据格式全面拥抱 Apache Arrow,与 pandas、Spark、DuckDB 近零拷贝互通。

特性清单里最值得记的四条:

  • Rust 实现,多线程并行加 SIMD 向量化
  • 惰性与即时两种执行模式,带查询优化器
  • 超出内存的数据集可用流式引擎处理
  • 表达式 API 富有表达力,可插件扩展

2、快的三个来源

Polars 的性能来自三层叠加。第一层是并行执行:Rust 无 GIL,所有核都能吃满,同样的 groupby 聚合,pandas 单核跑 8 秒的活,Polars 在 8 核机器上常在 1 秒出头。第二层是列式内存布局加 SIMD:数据按列紧凑存放,缓存命中率高,向量化指令一次处理多条数据。第三层是惰性执行——用 scan_csv、scan_parquet 声明数据源,链式写完过滤、聚合、排序,最后调用 collect() 时,查询优化器先审视整棵表达式树,做谓词下推、列削减、操作合并,然后才生成执行计划。这个模型对习惯 SQL 的人非常自然。

3、快速上手

README 里的官方示例完整展示了惰性 API 的典型链路,逐字摘录如下:

import polars as pl

q = (
    pl.scan_parquet("data.parquet")
    .filter(pl.col("category") == "electronics")
    .group_by("merchant")
    .agg(
        pl.col("amount").sum().alias("total_amount"),
        pl.len().alias("number_of_transactions"),
    )
    .sort("total_amount", descending=True)
)

df = q.collect()

从上往下读:scan_parquet 声明数据源(scan 是惰性模式,read 是即时模式);filter 用 pl.col("category") 引用列;agg 同时算两列聚合,alias 命名输出列。直到 collect() 才真正执行,此时优化器介入。

如果数据集大过内存,把最后一行换成 q.collect(engine="streaming"),同样的查询走流式引擎分批处理——代码不变,规模上了一个数量级。

4、表达式与生态扩展

表达式 API 是 Polars 的灵魂。pl.col("amount").sum() 里的 .sum() 不是立即计算,而是返回一个待执行的表达式对象,可以继续组合:嵌套窗口、条件分支 pl.when(...).then(...).otherwise(...)、在同一个 select 里对同一列派生多个输出。表达式发生在查询计划里,优化器看得见全貌,这是它比逐行调用型 API 快的根本原因。

工程上还有几个值得知道的点:

能力 说明
表达式插件 用 Rust 写自定义表达式并注册
I/O 插件 自定义数据源接入扫描层
GPU 加速 NVIDIA GPU 为可选启用项
Polars Cloud 分布式集群扩展

版本兼容有一个细节:不支持 AVX2 指令集的老 CPU 上需要设置 LTS_CPU=1 安装长期支持构建。性能对标可参考 官方文档 附带的 PDS-H 基准集。

5、对比 pandas 与迁移建议

把两个引擎放在决策清单里看:十 GB 以内的探索分析,pandas 生态更熟、答案更多;重复执行的批处理管道,Polars 的多核优势持续兑现;数据超过内存,流式引擎最省事;团队 SQL 背景浓,表达式语义也更接近 SQL。

迁移成本比想象中低:pd.read_parquet 换 pl.scan_parquet,groupby() 换 group_by(),df["col"] 换 pl.col("col")。思维转变只有一个——从"立即改数据"转为"声明变换再 collect"。另一个忠告:不要逐行迭代,.iter_rows() 等于放弃全部并行优势。

6、总结

Polars 证明了数据框引擎可以既快又好用:Rust 多线程内核、Arrow 内存格式、带优化器的惰性执行、超内存流式处理,四件套对 pandas 单线程模型构成降维打击。对于新建的数据管道和性能敏感的批处理任务,建议默认选 Polars、用 scan_parquet 加 collect 的惰性写法起步;对于存量 pandas 代码和重交互的探索场景,建议保留 pandas 做前端、通过 Arrow 互通,按瓶颈逐步迁移——两个引擎共存是当下最务实的架构。

相关推荐

获取系统SDK版本、判断手机ROM
精选Code

获取系统SDK版本、判断手机ROM

Build获取系统SDK版本Android中部分API的使用,需要在特定的SDK版本之后才能使用,因此在兼容老版本SDK的时候,经常需要判断API的版本。各种Android版本的对应关系参考《Android各版本对应的SDK版本》判断手机ROM有时候需要判断手机系统的ROM,检测ROM是MIUI、EMUI还是Flyme,可以使用getprop命令,去系统build.prop文件(关于build.p

4.2k
AndroidStudio中各种中文乱码问题
精选Code

AndroidStudio中各种中文乱码问题

AndroidStudio中各种中文乱码问题1、编译Java错误信息乱码在出现这个Annotation processors must be explicitly declared now...问题的时候,正好也发现AndroidStudio Build Output错误信息都乱码。经常遇到各种问题,习惯了,现在遇到的问题,都是以后的答案。 1.1、修改项目build.gradle(无效)在整个p

2.8k
AndroidStudio 报错:has no declaration in the base values folder
Code

AndroidStudio 报错:has no declaration in the base values folder

在资源文件中正常定义的值,也能编译运行。昨天还正常,今天一打开就报错。应该又是AndroidStudio自身的Bug了。原因众说纷纭,参考Stack Overflow 一篇类似的讨论。解决:File => Invalidate Caches / Restart => Invalidate and Restart.

4.9k