Polars窗口函数内降序排序的实现方式及order_by参数用途疑问
Polars窗口函数内降序排序的实现方式及order_by参数用途疑问
嘿,我刚学Polars一周左右,一直卡在怎么实现类似SQL里sum(...) over(partition by... order by... DESC)的窗口聚合逻辑上,折腾了好几种写法,终于摸出点头绪,也想聊聊关于窗口函数里order_by参数的困惑。
最开始我写了这段代码,结果输出完全不对,简直一团糟:
df.group_by('merchant_id', 'month')\ .agg(sum_share=pl.col('amount').sum())\ .with_columns(sum_share=pl.col('sum_share')/(pl.col('sum_share').sum().over('month')))\ .sort(['month', 'sum_share'], descending=[False,True])\ .with_columns( cumulative_sales=pl.col("sum_share") .cum_sum() .over("month", order_by=pl.col("sum_share").reverse()))
这时候我就觉得,或许不该在over()里搞排序,不如先把整个数据集按需求排好序,再添加累计求和的列?于是我改成了这样:
df.group_by('merchant_id', 'month')\ .agg(sum_share=pl.col('amount').sum())\ .with_columns(sum_share=pl.col('sum_share')/(pl.col('sum_share').sum().over('month')))\ .sort(['month', 'sum_share'], descending=[False,True])\ .with_columns( cumulative_sales=pl.col("sum_share") .cum_sum() .over("month"))
这段代码能跑了,但我又产生了疑问——窗口函数里的order_by参数到底是干嘛用的?既然没法直接实现降序(虽然确实不常用),那它存在的意义是什么?
后来我终于试出了能正常工作的版本,核心是用cum_sum(reverse=True)配合窗口的order_by:
# this worked (df.group_by('merchant_id', 'month')\ .agg(sum_share=pl.col('amount').sum())\ .with_columns(sum_share=pl.col('sum_share')/(pl.col('sum_share').sum().over('month')))\ .sort(['month', 'sum_share'], descending=[False,True])\ .with_columns( cumulative_sales=pl.col("sum_share") .cum_sum(reverse=True) .over("month", order_by=pl.col("sum_share")))\ .with_columns(share_of_m_for_merch=pl.col("month").n_unique().over('merchant_id'), help=pl.col('cumulative_sales').filter(pl.col('cumulative_sales')>=0.2).min().over('month'))\ .filter(pl.col('cumulative_sales')<=pl.col('help'))\ )
这段代码是用来找出每个月贡献至少20%营收的最少商家数量,通过cum_sum(reverse=True)和普通cum_sum配合实现的,输出结果大概是这样:
后来我也搞明白了,其实Polars窗口函数的order_by是用来定义窗口内计算的顺序,比如当你需要按某个字段升序计算累计值时,直接用它就能指定排序逻辑;而如果要实现降序的窗口累计,不能直接在order_by里加.reverse(),而是要配合聚合函数本身的reverse参数(比如cum_sum(reverse=True))来实现,这才是正确的打开方式。
备注:内容来源于stack exchange,提问作者user29365845
相关产品推荐
相关产品推荐

