如何将Pandas的groupby+resample逻辑转换为Polars实现?
在Polars中实现分组后时间重采样的正确方式
你有生成测试DataFrame的代码(生产环境数据结构更复杂):
import polars as pl import numpy as np import pandas as pd def create_timeseries_df(num_rows): date_rng = pd.date_range(start='1/1/2020', end='1/01/2021', freq='T') data = { 'date': np.random.choice(date_rng, num_rows), 'category': np.random.choice(['A', 'B', 'C', 'D'], num_rows), 'subcategory': np.random.choice(['X', 'Y', 'Z'], num_rows), 'value': np.random.rand(num_rows) * 100 } df = pd.DataFrame(data) df = df.sort_values('date') df.set_index('date', inplace=True, drop=False) df.index = pd.to_datetime(df.index) return df num_rows = 1000000 # 示例数据量 df = create_timeseries_df(num_rows)
原本使用Pandas执行的转换逻辑:
df_pd = df.copy() df_pd = df_pd.groupby(['category', 'subcategory']) df_pd = df_pd.resample('W-MON') df_pd.agg({ 'value': ['sum', 'mean', 'max', 'min'] }).reset_index()
因Pandas在生产环境处理速度不足,尝试改用Polars但触发错误:
# 转换为Polars DataFrame df_pl = pl.from_pandas(df) # 分组、重采样并聚合 df_pl = df_pl.group_by('category', 'subcategory') df_pl = df_pl.group_by_dynamic('date', every='1w', closed='right') df_pl.agg( pl.col('value').sum().alias('value_sum'), pl.col('value').mean().alias('value_mean'), pl.col('value').max().alias('value_max'), pl.col('value').min().alias('value_min') )
错误信息:AttributeError: 'GroupBy' object has no attribute 'group_by_dynamic'
解决方案
Polars中无法通过GroupBy对象调用group_by_dynamic,正确的做法是直接使用group_by_dynamic方法,通过by参数指定分组列,同时配置时间重采样参数:
df_pl = pl.from_pandas(df) # 直接用group_by_dynamic完成分组+时间重采样 result = df_pl.group_by_dynamic( 'date', every='1w', closed='right', by=['category', 'subcategory'] # 在这里指定分组列 ).agg( pl.col('value').sum().alias('value_sum'), pl.col('value').mean().alias('value_mean'), pl.col('value').max().alias('value_max'), pl.col('value').min().alias('value_min') )
细节对齐说明
如果需要和Pandas的W-MON(每周一作为周结束日)逻辑完全对齐,可通过offset参数调整时间窗口的起始/结束点:
result = df_pl.group_by_dynamic( 'date', every='1w', closed='right', offset='-6d', # 调整窗口,使周周期以周一为结束日 by=['category', 'subcategory'] ).agg( pl.col('value').sum().alias('value_sum'), pl.col('value').mean().alias('value_mean'), pl.col('value').max().alias('value_max'), pl.col('value').min().alias('value_min') )
内容的提问来源于stack exchange,提问作者girdeux
相关产品推荐
相关产品推荐

