You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Polars中实现c1分组内的(c2,c3)组排名?

实现Polars分组内的(c2,c3)组合排名

方法一:使用窗口函数over()(推荐)

直接通过dense_rank()窗口函数,在c1分组内对(c2,c3)的唯一组合分配连续排名,再减1得到从0开始的编号,这是最简洁的实现方式:

import polars as pl

df = pl.from_repr("""
┌─────┬─────┬─────┐
│ c1  ┆ c2  ┆ c3  │
│ --- ┆ --- ┆ --- │
│ str ┆ str ┆ i64 │
╞═════╪═════╪═════╡
│ a   ┆ a   ┆ 1   │
│ a   ┆ a   ┆ 1   │
│ a   ┆ b   ┆ 1   │
│ a   ┆ c   ┆ 1   │
│ d   ┆ a   ┆ 1   │
│ d   ┆ b   ┆ 1   │
└─────┴─────┴─────┘
""")

result = df.with_columns(
    rank=pl.dense_rank().over("c1").order_by(["c2", "c3"]) - 1
)

print(result)

运行结果:

┌─────┬─────┬─────┬──────┐
│ c1  ┆ c2  ┆ c3  ┆ rank │
│ --- ┆ --- ┆ --- ┆ ---  │
│ str ┆ str ┆ i64 ┆ i64  │
╞═════╪═════╪═════╪══════╡
│ a   ┆ a   ┆ 1   ┆ 0    │
│ a   ┆ a   ┆ 1   ┆ 0    │
│ a   ┆ b   ┆ 1   ┆ 1    │
│ a   ┆ c   ┆ 1   ┆ 2    │
│ d   ┆ a   ┆ 1   ┆ 0    │
│ d   ┆ b   ┆ 1   ┆ 1    │
└─────┴─────┴─────┴──────┘

原理说明:

  • dense_rank():在c1分组内,对(c2,c3)的不同组合分配连续的排名(相同组合共享同一排名),默认从1开始。
  • over("c1"):指定分组范围为c1的每个取值。
  • order_by(["c2", "c3"]):确定排名的顺序(按c2、c3升序排列)。
  • 减1操作:将排名从1起始转换为0起始,匹配需求。

方法二:改进GroupBy+Join模式

基于你已掌握的全局排名思路修改,通过分组内生成唯一组合再分配排名,最后关联回原表:

result = df.join(
    # 按c1分组,提取每个组内的(c2,c3)唯一组合
    df.group_by("c1", maintain_order=True)
    .agg(pl.col(["c2", "c3"]).unique().alias("pairs"))
    .explode("pairs")
    # 拆分结构体为c2、c3列,并在每个c1分组内生成从0开始的排名
    .with_columns(
        c2=pl.col("pairs").struct.field("c2"),
        c3=pl.col("pairs").struct.field("c3"),
        rank=pl.int_range(0, pl.len()).over("c1")
    )
    .drop("pairs"),
    on=["c1", "c2", "c3"]
)

print(result)

此方法也能得到与期望一致的结果,但代码复杂度高于窗口函数方案。

内容的提问来源于stack exchange,提问作者ldrg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:21:02