如何将Pandas分组滚动窗口Lambda计算转为Polars实现
Pandas滚动加权求和逻辑的Polars正确实现
错误原因分析
你之前的代码报错是因为Polars的GroupBy对象没有select方法,同时自定义函数的逻辑和原Pandas代码不符(原Pandas是直接对加权项求和,不是加权平均),需要调整实现方式。
正确Polars实现代码
import polars as pl lookback_period = 5 # 构造Polars DataFrame(对齐原Pandas数据) df_data = pl.DataFrame({ 'date': [ '31/12/2021', '07/01/2022', '14/01/2022', '21/01/2022', '28/01/2022', '04/02/2022', '11/02/2022', '18/02/2022', '25/02/2022', '04/03/2022', '11/03/2022', '18/03/2022', '25/03/2022', '01/04/2022', '08/04/2022', '14/04/2022', '22/04/2022', '29/04/2022', '06/05/2022', '13/05/2022', '20/05/2022' ], 'close-LDPM': [ 10.87, 11.04, 11.36, 11.01, 12.07, 12.44, 12.38, 10.06, 10.12, 8.1, 8.45, 9.05, 9.27, 9.51, 9.66, 8.49, 8.53, 7.96, 7.71, 7.65, 7.77 ], 'ticker': ['ERIC'] * 21, 'timeframe': ['1 W'] * 21 }) # 定义对齐原Pandas逻辑的自定义滚动函数 def custom_weighted_sum(s: pl.Series) -> float: # 仅当窗口长度达到lookback_period时计算,否则返回None(对应NaN) if len(s) != lookback_period: return None # 反转序列,使最新元素对应权重1/1,倒数第二个对应1/2,以此类推 reversed_series = s.reverse() # 生成权重:1/1, 1/2, ..., 1/5 weights = pl.Series([1/i for i in range(1, lookback_period + 1)]) # 计算加权和 return (reversed_series * weights).sum() # 分组(ticker+timeframe)后应用滚动窗口计算 df_data = df_data.with_columns( LDPS_w = pl.col('close-LDPM') .rolling(window_size=lookback_period, min_periods=lookback_period) .apply(custom_weighted_sum) .over(['ticker', 'timeframe']) ) print(df_data)
关键说明
- Polars分组滚动的正确姿势:使用
over子句直接在列表达式上实现分组内的滚动计算,无需先调用group_by,代码更简洁。 - 对齐原逻辑:函数中先反转序列,确保最新的元素对应最大的权重(1/1),和原Pandas代码中
x[-i]/i的逻辑完全匹配。 - 控制窗口生效条件:通过
min_periods=lookback_period和函数内的长度判断,确保只有窗口元素数量达到5时才输出计算结果,否则返回None(对应Pandas的NaN)。
内容的提问来源于stack exchange,提问作者iKiok
相关产品推荐
相关产品推荐

