Polars分组聚合如何无需join获取组内最大值对应整行数据
Polars 分组取极值对应整行的无Join实现
完全不需要额外做join关联,Polars原生支持在聚合阶段直接返回极值对应的完整行数据,性能比先聚合再join的方案高很多,以下是可直接复用的实现方式。
推荐写法:top_k 聚合(语义最直观)
top_k 表达式可以直接按指定列排序,返回分组内排序靠前的N条记录的所有列值,取单组最大值时传入k=1即可,最后通过unnest展开结构体得到平铺结果:
import polars as pl df = pl.DataFrame({ 'class': ['a', 'a', 'b', 'b'], 'name': ['Ron', 'Jon', 'Don', 'Von'], 'score': [0.2, 0.5, 0.3, 0.4] }) result = df.group_by('class').agg( pl.all().top_k(k=1, by='score') ).unnest('name', 'score')
执行后输出和join方案完全一致:
shape: (2, 3) ┌───────┬──────┬───────┐ │ class ┆ name ┆ score │ │ --- ┆ --- ┆ --- │ │ str ┆ str ┆ f64 │ ╞═══════╪══════╪═══════╡ │ a ┆ Jon ┆ 0.5 │ │ b ┆ Von ┆ 0.4 │ └───────┴──────┴───────┘
注意:如果分组内存在多个score相同的最大值行,该方法会返回所有并列最大值的行,不会丢数据。
备选写法:排序后取末位
如果需要自定义排序逻辑,可以在聚合阶段对分组内所有行按score排序,直接取排序后的最后一行(即最大值行)的所有字段,不需要额外关联:
result = df.group_by('class').agg( pl.all().sort_by('score').last() )
该写法输出和上述方案完全一致。
补充说明
- 若需要取分组内score最小值对应的整行,将
top_k替换为bottom_k,或排序后取.first()即可 - 若需要取分组内score最大的前N行,直接调整
top_k的k参数为对应数值即可,无需修改其他逻辑 - 两种无join方案都仅需对原表做一次分组遍历,不需要维护join的哈希映射,在大数据量场景下性能比join方案高30%到数倍不等
内容的提问来源于stack exchange,提问作者Vikash Balasubramanian
相关产品推荐
相关产品推荐

