如何用Polars实现两个DataFrame逐列滚动计算?
在Polars中实现对应列的滚动协方差、相关系数与斜率计算
首先构造示例数据:
import polars as pl import numpy as np # 生成与示例结构一致的Polars DataFrame X = pl.DataFrame({f"id{i}": np.random.randn(200) for i in range(100)}) Y = pl.DataFrame({f"id{i}": np.random.randn(200) for i in range(100)})
核心实现思路
Polars没有直接提供类似Pandasrolling().cov(Y)这种跨DataFrame的逐列滚动计算API,需要通过合并DataFrame+自定义窗口表达式来实现,核心是基于统计公式手动推导滚动计算逻辑(匹配Pandas默认的ddof=1无偏估计):
- 滚动协方差:
sum((x - x_mean)(y - y_mean)) / (window_size - 1) - 滚动方差:
sum((x - x_mean)²) / (window_size - 1) - 滚动相关系数:
协方差 / (x_std * y_std) - 滚动斜率:
协方差 / x_var
完整代码实现
window_size = 5 # 合并X与Y,给Y的列添加前缀避免命名冲突 merged_df = X.hstack(Y.rename({col: f"y_{col}" for col in Y.columns})) # 生成所有列的滚动计算表达式 expressions = [] for col in X.columns: x_col = col y_col = f"y_{col}" # 计算窗口内的X、Y列均值(min_periods匹配Pandas默认行为,仅当窗口满5行时计算) x_win_mean = pl.col(x_col).rolling_mean(window_size=window_size, min_periods=window_size) y_win_mean = pl.col(y_col).rolling_mean(window_size=window_size, min_periods=window_size) # 滚动协方差(ddof=1) cov = ((pl.col(x_col) - x_win_mean) * (pl.col(y_col) - y_win_mean)).rolling_sum( window_size=window_size, min_periods=window_size ) / (window_size - 1) expressions.append(cov.alias(f"{col}_cov")) # 滚动X列方差(ddof=1) x_var = ((pl.col(x_col) - x_win_mean)**2).rolling_sum( window_size=window_size, min_periods=window_size ) / (window_size - 1) expressions.append(x_var.alias(f"{col}_var")) # 滚动相关系数 y_var = ((pl.col(y_col) - y_win_mean)**2).rolling_sum( window_size=window_size, min_periods=window_size ) / (window_size - 1) corr = cov / (x_var.sqrt() * y_var.sqrt()) expressions.append(corr.alias(f"{col}_corr")) # 滚动斜率 slope = cov / x_var expressions.append(slope.alias(f"{col}_slope")) # 执行计算并得到结果 result = merged_df.select(expressions)
结果说明
- 结果DataFrame中,每一列对应原始
id{i}列的滚动计算结果:id{i}_cov是滚动协方差,id{i}_var是X列的滚动方差,id{i}_corr是滚动相关系数,id{i}_slope是滚动斜率 - 前4行结果为
null,与Pandas默认的min_periods=window_size行为一致,仅当窗口包含完整5行数据时才输出有效计算值
内容的提问来源于stack exchange,提问作者c dai
相关产品推荐
相关产品推荐

