Polars 中如何执行无分组聚合操作(全局聚合)

4次阅读

Polars 中如何执行无分组聚合操作(全局聚合)

在 Polars 中,无需借助虚拟分组列即可直接对整个 DataFrame 执行全局聚合,只需在 select() 上下文中使用纯聚合表达式(如 .mean()、.sum()、.first() 等),框架会自动返回单行结果。

在 polars 中,无需借助虚拟分组列即可直接对整个 dataframe 执行全局聚合,只需在 `select()` 上下文中使用纯聚合表达式(如 `.mean()`、`.sum()`、`.first()` 等),框架会自动返回单行结果。

Polars 的设计哲学强调“表达式优先”与“上下文感知”,其中 select() 是一个关键上下文:当 select() 中所有列均为聚合表达式(即不包含任何非聚合的逐行操作)时,Polars 会隐式触发全局聚合(global aggregation),自动将整个 DataFrame 视为一个逻辑组,并输出仅含一行的结果。这正是实现“无 group_by 的 .agg()”的标准、高效且符合惯用法的方式。

相比手动添加 dummy 列再 group_by().agg(),该方法更简洁、零冗余、性能更优——既避免了临时列开销,也绕过了分组哈希计算,底层直接进行单次遍历扫描。

以下是一个完整示例:

import polars as pl  df = pl.DataFrame({     "a": [1, 2, 3, 4, 5],     "b": [0, 0, 1, 1, 1],     "c": ["x", "y", "z", "w", "v"] })  # ✅ 正确:全部为聚合表达式 → 自动全局聚合,返回 shape: (1, 3) result = df.select(     pl.col("a").mean().alias("a_mean"),     pl.col("b").sum().alias("b_sum"),     pl.col("c").last().alias("c_last") )  print(result)

输出:

shape: (1, 3) ┌──────────┬───────┬────────┐ │ a_mean   ┆ b_sum ┆ c_last │ │ ---      ┆ ---   ┆ ---    │ │ f64      ┆ i64   ┆ str    │ ╞══════════╪═══════╪════════╡ │ 3.0      ┆ 3     ┆ v      │ └──────────┴───────┴────────┘

⚠️ 注意事项:

  • 若 select() 中混入非聚合表达式(例如 pl.col(“a”) 或 pl.col(“a”) + 1),Polars 将报错:InvalidOperationError: expected all expressions to be aggregations。这是有意为之的安全机制,确保语义明确。
  • 所有支持聚合的 Polars 表达式均可在此使用,包括但不限于:.sum()、.min()、.max()、.std()、.count()、.n_unique()、.quantile(0.5)、.list() 等。
  • 如需同时保留部分原始列并聚合其他列,应改用 with_columns() + 聚合表达式(此时聚合结果会广播至原行数),或先聚合再 join —— 但这就不再是“单行输出”场景。

总结:df.select() 是 Polars 中执行轻量级、单行全局聚合的首选范式。它语义清晰、性能优越、无需 hack,是真正契合 Polars 表达式引擎设计理念的地道写法。

text=ZqhQzanResources