本文介绍如何使用 polars 的表达式 api,在计算列众数(mode)时自动判别是否唯一;若存在多个频率最高的值,则返回 null 而非全部候选值,从而严格满足“唯一众数”语义。
本文介绍如何使用 polars 的表达式 api,在计算列众数(mode)时自动判别是否唯一;若存在多个频率最高的值,则返回 null 而非全部候选值,从而严格满足“唯一众数”语义。
在数据分析中,“众数”通常被定义为出现频率最高的单一值。但 Polars 默认的 .mode() 表达式会返回所有并列最高频的值(即支持多众数),这在需要明确“唯一主导值”的场景下可能引发逻辑歧义——例如统计学检验、业务规则校验或模型特征工程中,我们往往要求众数必须唯一,否则视为缺失(null)。
要实现“仅当众数唯一时返回该值,否则返回 null”,推荐使用 pl.when().then() 条件表达式进行显式控制:
import polars as pl
df = pl.DataFrame({"a": [1, 1, 2, 3], "b": [1, 1, 2, 2]})
result = df.select(
pl.when(pl.col("b").mode().len() == 1)
.then(pl.col("b").mode())
)
print(result)
输出:
shape: (2, 1) ┌──────┐ │ b │ │ --- │ │ i64 │ ╞══════╡ │ null │ │ null │ └──────┘
⚠️ 注意:.mode() 返回的是一个 Series(即使只有一个值),因此 pl.col("b").mode().len() 检查其长度是否为 1 是关键判断依据。上述写法会为每行生成一个结果(因 .mode() 在上下文中仍按列聚合,但 when/then 应用于聚合结果后,Polars 会广播填充),故返回两行 null —— 这是 Polars 默认的行对齐行为。
如需仅返回单个标量 null(而非多行 null),可进一步链式调用 .unique(maintain_order=True) 并取首项,或更简洁地使用聚合上下文:
# 推荐:在 select 中直接获取单值结果(一行一列)
single_mode = df.select(
pl.when(pl.col("b").mode().len() == 1)
.then(pl.col("b").mode())
.first() # 确保只返回一个值(即使 mode 返回多值,first 也只取第一个;但配合 when 后实际只触发一次)
).item() # 若确定结果唯一且非空,可用 item() 提取 Python 值;否则建议保留 Expr 链式操作
# 或更稳健的写法(显式处理空情况):
mode_expr = pl.col("b").mode()
df.select(
pl.when(mode_expr.len() == 1)
.then(mode_expr.first())
.otherwise(None) # 显式指定 else 分支为 None(即 null)
).to_series().to_list() # → [None]
✅ 总结:
- 核心逻辑是 mode().len() == 1 判断唯一性;
- pl.when().then() 提供声明式条件分支能力,比手动 Python 逻辑更高效、可并行;
- 避免在 .mode() 后直接 .first() 或索引访问——未加条件保护时可能引发运行时错误或掩盖多众数问题;
- 该模式可轻松复用于任意列或自定义表达式,是构建健壮数据管道的重要实践。











