如何在Polars中用group_by_dynamic复现Pandas季度分组重采样计数
Polars对齐Pandas季度重采样实现方案
核心疑问解答
every='3mo' 不等价于 Pandas的resample('Q'):
- Pandas的
Q是固定自然季度规则,窗口边界固定为每年3、6、9、12月的最后一天,和数据起始时间无关 - Polars的
3mo是相对偏移,从数据最早时间点开始每3个月切一个窗口,边界随起始时间变化,无法对齐自然季度
无性能损耗的对齐实现
不需要开启include_boundaries(无额外性能开销),直接使用Polars原生季度频率+窗口偏移参数即可完全对齐Pandas输出:
import polars as pl import pandas as pd # 构造测试数据集 df = pl.DataFrame({ 'date': pd.date_range("2018-01-01", periods=365*24, freq='H') }).with_columns( pl.when(pl.int_range(pl.len()) < 400) .then(pl.lit('fire')) .otherwise(pl.lit('water')) .alias('pokemon_type') ) # 完全对齐Pandas resample('Q')的统计逻辑 result = df.group_by_dynamic( index_column='date', every='1q', # 按自然季度切分,和Pandas 'Q'规则一致 offset='-1ns', # 窗口偏移1纳秒,让默认返回的左边界标签落到季度最后一天 group_by='pokemon_type' ).agg( pl.len().alias('total') )
实现原理
Polars动态窗口默认是左闭右开区间,比如2018年Q1的窗口范围是[2018-01-01 00:00:00, 2018-04-01 00:00:00),默认返回的标签是左边界2018-01-01。给窗口加-1ns偏移后,窗口范围变为[2017-12-31 23:59:59.999999999, 2018-03-31 23:59:59.999999999),默认返回的左边界截断后正好是2018-03-31,也就是Pandas返回的季度最后一天标签。
运行结果和Pandas输出完全一致:
shape: (5, 3) ┌──────────────┬─────────────────────┬───────┐ │ pokemon_type ┆ date ┆ total │ │ str ┆ datetime[ns] ┆ u32 │ ╞══════════════╪═════════════════════╪═══════╡ │ fire ┆ 2018-03-31 00:00:00 ┆ 400 │ │ water ┆ 2018-03-31 00:00:00 ┆ 1760 │ │ water ┆ 2018-06-30 00:00:00 ┆ 2184 │ │ water ┆ 2018-09-30 00:00:00 ┆ 2208 │ │ water ┆ 2018-12-31 00:00:00 ┆ 2208 │ └──────────────┴─────────────────────┴───────┘
内容的提问来源于stack exchange,提问作者supersick
相关产品推荐
相关产品推荐

