首页
/ Polars 0.19 升级指南:水平聚合拆分、all/any 语义变更与 groupby/apply 重命名迁移详解

Polars 0.19 升级指南:水平聚合拆分、all/any 语义变更与 groupby/apply 重命名迁移详解

2026-09-05 20:05:53作者:凤尚柏Louis

本文基于 Polars 官方升级文档 0.19.md,系统讲解 Polars 0.19 版本的全部破坏性变更与弃用事项,并结合当前仓库源码逐条印证:聚合函数如何从“垂直+水平”双模式拆分为独立的 *_horizontal 函数族、all/any 对 null 的处理语义变化、错误类型从 ValueErrorTypeError 的收敛、表达式输入解析逻辑的统一,以及 shuffle/sample 改用内部随机种子后的 set_random_seed 用法;同时覆盖 groupby 更名为 group_byapply 全面并入 map_* 命名族的迁移方式,读完即可在 0.19 及之后的版本中完成平滑升级。

破坏性变更(Breaking changes)

聚合函数不再支持水平计算

这是 0.19 中最核心的行为变更。在此之前,summinmax 等聚合函数被“重载”设计:传入多列时执行水平(横向)计算,传入单列时执行垂直(纵向)计算。0.19 引入了专门负责水平计算的新函数族,并弃用旧的重载行为——聚合函数从此只保留垂直计算语义,水平计算必须显式使用 *_horizontal 变体(如 sum_horizontal)。

变更前(0.18 及以前,多列输入触发水平计算)

>>> df = pl.DataFrame({'a': [1, 2], 'b': [11, 12]})
>>> df.select(pl.sum('a', 'b'))  # horizontal computation
shape: (2, 1)
┌─────┐
│ sum │
│ --- │
│ i64 │
╞═════╡
│ 12  │
│ 14  │
└─────┘

变更后(0.19,同一写法变为垂直计算,形状从 (2, 1) 变为 (1, 2))

>>> df = pl.DataFrame({'a': [1, 2], 'b': [11, 12]})
>>> df.select(pl.sum('a', 'b'))  # vertical computation
shape: (1, 2)
┌─────┬─────┐
│ a   ┆ b   │
│ --- ┆ --- │
│ i64 ┆ i64 │
╞═════╪═════╡
│ 323  │
└─────┴─────┘

需要水平求和时,改用新函数即可恢复旧行为:

>>> df.select(pl.sum_horizontal('a', 'b'))

从源码结构看,水平聚合函数族集中定义在 horizontal.py 中,共提供 6 个函数:all_horizontal(第 20 行)、any_horizontal(第 65 行)、max_horizontal(第 110 行)、min_horizontal(第 145 行)、sum_horizontal(第 180 行)与 mean_horizontal(第 220 行)。其中值得注意的参数细节是:

  • sum_horizontalmean_horizontal 额外提供 ignore_nulls: bool = True 参数:默认忽略 null(第三行 3 + null 结果为 3);设为 False 时,只要输入存在 null,该行输出即为 null;
  • all_horizontal / any_horizontal 采用 Kleene 逻辑(三值逻辑)处理 null:列中存在 null 且没有 False(或 True)时,输出为 null 而非布尔值;
  • 所有水平函数统一通过 parse_into_list_of_expressions 解析输入:字符串按列名解析,其他非表达式输入按字面量解析,最终调用 Rust 侧的 plr.*_horizontal 内核函数。

而垂直聚合入口(如 pl.sum)则位于 vertical.py,两者在 aggregation/init.py 中合并导出,这就是“同一函数名只保留一种语义、水平计算走独立命名空间”这一 API 设计的代码体现。

all / any 语义更新

0.19 中 all 不再把 null 当作 False 处理,而是默认忽略 null 值。以 [True, None] 为例:

变更前

>>> pl.Series([True, None]).all()
False

变更后

>>> pl.Series([True, None]).all()
True

同时,anyalldrop_nulls 参数被重命名为 ignore_nulls,并改为**仅关键字(keyword-only)**参数;原参数设为 False 时在某些情况下错误地返回 None 的 bug 也一并修复。要恢复旧行为,需设置 ignore_nulls=False 并自行检查 None 输出:

>>> pl.Series([None, True]).all(ignore_nulls=False)  # 启用 Kleene 逻辑,返回 None

当前仓库源码 series.pySeries.any(第 1750 行)与 Series.all(第 1792 行)均已签名化为 ignore_nulls: bool = True 的关键字参数,文档字符串明确提示“Enable Kleene logic by setting ignore_nulls=False”,与升级文档描述完全一致。

大量方法的错误类型改善

Polars 对错误消息的改进是持续性的工作。0.19 对 Python 代码库做了一次全面排查,重点变化是许多 ValueError 被修正为 TypeError,使异常类型与实际错误性质(如传入了不支持的类型)对应得更准确:

变更前

>>> pl.Series(values=15)
...
ValueError: Series constructor called with unsupported type; got 'int'

变更后

>>> pl.Series(values=15)
...
TypeError: Series constructor called with unsupported type 'int' for the `values` parameter

如果你的代码依赖 except ValueError 捕获 Polars 的构造/参数错误,升级后这类捕获会失效,应改为捕获 TypeError 或更宽泛的 Exception

表达式输入解析逻辑更新

selectwith_columns 等方法接受一个或多个表达式,同时也接受字符串、整数、列表等其他输入并尝试将其解释为表达式。0.19 统一了内部解析逻辑,使不同输入类型的解释更加一致。文档给出的例子恰好说明了一个“隐式行为消失”的变化——传入 None 不再被静默忽略,而是被解析为一个 null 字面量列:

变更前

>>> pl.DataFrame({'a': [1, 2]}).with_columns(None)
shape: (2, 1)
┌─────┐
│ a   │
│ --- │
│ i64 │
╞═════╡
│ 1   │
│ 2   │
└─────┘

变更后

>>> pl.DataFrame({'a': [1, 2]}).with_columns(None)
shape: (2, 2)
┌─────┬─────────┐
│ a   ┆ literal │
│ --- ┆ ---     │
│ i64 ┆ null    │
╞═════╪═════════╡
│ 1   ┆ null    │
│ 2   ┆ null    │
└─────┴─────────┘

这意味着过去“传入 None 悄悄不产生任何列”的用法现在会真正增加一列;若依赖该隐式行为,升级后应显式传入空表达式列表或不传参。

shuffle / sample 改用 Polars 内部随机种子

此前 shufflesample 等随机操作会受 Python 内置 random.seed 的影响,升级后该控制方式失效,取而代之的是新的全局函数 pl.set_random_seed

变更前

import random

random.seed(1)

变更后

import polars as pl

pl.set_random_seed(1)

当前仓库中该函数实现于 random.py(第 9–22 行):接收一个小于 2⁶⁴ 的非负整数作为种子,透传至 Rust 内核 plr.set_random_seed,用于决定 shuffle 顺序等随机行为。由于种子作用在 Polars 内部而非 Python 的 random 模块上,依赖 random.seed 复现 Polars 随机结果的脚本必须整体改为 pl.set_random_seed

弃用事项(Deprecations)

官方文档说明,0.19 带来了大量命名调整,升级时大概率会遇到 DeprecationWarning。如果想先升级、之后再逐步清理弃用警告,可在代码中临时添加:

import warnings

warnings.filterwarnings("ignore", category=DeprecationWarning)

groupby 更名为 group_by

文档明确指出这并非轻率的改动:“group by” 本是两个独立的词,而 Polars 的命名规范要求用下划线分隔,因此 groupby 统一更名为 group_by。官方建议直接用全局查找替换完成迁移:

  • 查找:.groupby(
  • 替换:.group_by(

从当前仓库源码确认,frame.py 第 7075 行定义的正是 DataFrame.group_bygroup_by.py 模块则承载了 GroupBy / LazyGroupBy 的实现,旧名仅作为弃用别名存在,语义完全不变。

apply 更名为 map_*

文档指出 apply 是 Polars API 中最容易被误用的部分——大量用户来自 pandas,而 pandas 中 apply 的含义完全不同。0.19 将所有用户自定义函数相关能力统一收敛到 map 命名族,具体对应关系如下(此表直接继承自升级文档,迁移时应逐条对照):

Before After
Series/Expr.apply map_elements
Series/Expr.rolling_apply rolling_map
DataFrame.apply map_rows
GroupBy.apply map_groups
apply(GroupBy 模块级) map_groups
map map_batches

当前仓库源码与该对照表一一对应:

  • DataFrame.map_rows 定义于 frame.py 第 8651 行;
  • GroupBy.map_groupsLazyGroupBy.map_groups 等定义于 group_by.py(第 378、1042、1253 行);
  • Rust 侧类型桩 _plr.pyi 中可见 map_elements(第 116 行)、map_rows(第 673 行)、map_batches(第 1155 行)、rolling_map(第 1843 行)、map_groups(第 2434 行)的完整签名,确认各旧名在新版本中均已映射到对应的 map_* 入口。

迁移要点小结

结合 0.19.md 与上述源码证据,升级到 0.19 时的行动清单为:

  1. 审计聚合调用:搜索传入多列的 pl.sum / pl.min / pl.max / pl.mean 调用,将其中本意为“按行横向计算”的场景改写为 sum_horizontal 等函数(源码位于 horizontal.py);
  2. 检查布尔断言:依赖 all 遇 null 得 False 的代码需改为显式处理,或改用 ignore_nulls=False 保留旧语义;
  3. 修正异常捕获:将针对构造/参数错误的 except ValueError 调整为 TypeError
  4. 排查隐式 None 表达式with_columns(None) 等写法现在会产生字面量 null 列;
  5. 替换随机种子random.seed 全部替换为 pl.set_random_seedrandom.py);
  6. 批量重命名.groupby(.group_by(apply / rolling_apply / map → 上表中的 map_* 对应项;
  7. 如需先升级再清理,可临时 warnings.filterwarnings("ignore", category=DeprecationWarning) 屏蔽弃用警告。
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.12 K
2.72 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
528
588
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
906
1.83 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
854
1.34 K
docsdocs
暂无描述
Markdown
891
5.79 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.53 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.34 K
1.45 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
988
506
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
540
384