
本文介绍如何在 polars 中基于分组(如列 a),为每组找出另一列(如 x)极值(最大或最小)所在行的指定列(如 b)值,并将其广播为新列(如 y),适用于高效聚合与特征构造场景。
本文介绍如何在 polars 中基于分组(如列 a),为每组找出另一列(如 x)极值(最大或最小)所在行的指定列(如 b)值,并将其广播为新列(如 y),适用于高效聚合与特征构造场景。
在 Polars 数据处理中,一个常见需求是:按某列分组后,获取另一列极值(如 x 的最大值)所对应行中某个字段(如 B)的值,并将该值填充到组内所有行。这不同于常规聚合(如 .max() 返回标量),而是需要“索引对齐”式的取值——即先定位极值位置,再提取同位置的其他列内容。
核心思路是组合使用三个关键表达式:
-
pl.col("x").arg_max():返回列x中最大值的索引位置(整数); -
pl.col("B").get(idx):根据索引idx从列B中提取对应值; -
.over("A"):将上述操作以窗口形式按列A分组独立执行。
完整实现如下:
import polars as pl
df = pl.DataFrame({
'A': ['a0', 'a0', 'a1', 'a1'],
'B': ['b1', 'b2', 'b1', 'b2'],
'x': [0, 10, 5, 1]
})
result = df.with_columns(
pl.col("B").get(pl.col("x").arg_max()).over("A").alias("y")
)
print(result)
输出结果符合预期:
shape: (4, 4) ┌─────┬─────┬─────┬─────┐ │ A ┆ B ┆ x ┆ y │ │ --- ┆ --- ┆ --- ┆ --- │ │ str ┆ str ┆ i64 ┆ str │ ╞═════╪═════╪═════╪═════╡ │ a0 ┆ b1 ┆ 0 ┆ b2 │ │ a0 ┆ b2 ┆ 10 ┆ b2 │ │ a1 ┆ b1 ┆ 5 ┆ b1 │ │ a1 ┆ b2 ┆ 1 ┆ b1 │ └─────┴─────┴─────┴─────┘
✅ 注意事项:
- 若需获取最小值对应行的
B值,将arg_max()替换为arg_min()即可; -
get()在索引越界时会返回null,建议确保每组内x非空;可加.drop_nulls()或用pl.all().is_not_null()预检; -
arg_max()对存在多个相同极值的情况,返回第一个匹配索引(稳定且可预期); - 该方案全程向量化、零 Python 循环,性能远优于
group_by().apply()等自定义逻辑。
此模式可灵活扩展:例如同时获取 B 和 C 两列的极值对应值,只需重复 pl.col("C").get(...) 表达式即可。掌握 get + arg_{min/max} + over 组合,是写出简洁、高效 Polars 窗口逻辑的关键技能之一。










