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

如何在Polars中实现窗口函数式的多列唯一值对计数?

在Polars中高效统计分组内多列唯一值对的窗口实现方法

需求说明

需要实现窗口函数,统计指定分组(context列)内column1与column2的唯一值对数量,功能等价于多列组合的n_unique,但支持窗口上下文计算。

示例数据:

import polars as pl

df = pl.DataFrame({
    'context': [1, 1, 1,  2, 2, 2,  3, 3, 3],
    'column1': [1, 1, 0,  1, 0, 0,  1, 0, 1],
    'column2': [1, 0, 0,  0, 1, 1,  1, 0, 1]
})

问题重现

直接调用pl.n_unique('column1', 'column2').over('context')会触发ComputeError,因为当前n_unique不支持同时传入多列并结合窗口over使用:

# 报错代码
(
    df
    .with_columns(
        pl.n_unique('column1', 'column2').over('context').alias('n_unique')
    )
)

现有可行方案

通过concat_list将两列合并为列表列,再统计列表的唯一值数量,该方法可行但并非最优:

(   
    df
    .with_columns(
        pl.concat_list('column1', 'column2').alias('pair')
    )
    .with_columns(
        pl.n_unique('pair').over('context')
    )
)

更优实现方案

以下几种方法在性能或可读性上更具优势:

方案1:用struct替代list

结构体在Polars中处理效率高于列表,且语义更贴合"键值对"的概念:

(
    df
    .with_columns(
        pl.struct('column1', 'column2').alias('pair')
    )
    .with_columns(
        pl.n_unique('pair').over('context').alias('n_unique')
    )
)

方案2:先聚合再关联(适合大数据量场景)

先对分组计算唯一值对数量,再通过join将结果映射回原表,避免窗口函数的重复计算开销:

agg_df = df.group_by('context').agg(
    pl.n_unique(pl.struct('column1', 'column2')).alias('n_unique')
)

df.join(agg_df, on='context', how='left')

方案3:用hash组合列后统计唯一值

通过pl.hash将两列组合成哈希值,再统计哈希值的唯一数量,性能通常最优:

(
    df
    .with_columns(
        pl.hash('column1', 'column2').alias('pair_hash')
    )
    .with_columns(
        pl.n_unique('pair_hash').over('context').alias('n_unique')
    )
)

方案对比

  • struct方案:可读性强,性能优于列表方案,适合大多数常规场景
  • 聚合后关联:大数据量下性能最优,减少窗口函数的内存开销
  • hash方案:性能最高,但哈希存在极低的碰撞风险,需根据业务场景评估使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 20:01:13