如何在Polars中计算滚动相关性?含逐行相关实现需求
Polars原生实现滚动相关性
Polars目前没有内置的滚动相关系数函数,但可以通过皮尔逊相关系数的数学公式,结合滚动窗口统计量实现和Pandas rolling.corr一致的效果,无需转成Pandas处理。
实现思路
皮尔逊相关系数的核心公式为:
$$\text{corr}(x,y) = \frac{\text{cov}(x,y)}{\text{std}(x) \times \text{std}(y)}$$
其中:
- 协方差 $\text{cov}(x,y) = E[xy] - E[x]E[y]$
- 标准差 $\text{std}(x) = \sqrt{E[x^2] - (E[x])^2}$,$\text{std}(y)$ 同理
我们可以用Polars的滚动窗口函数计算这些关键统计量,再代入公式得到滚动相关性。
完整代码示例
import polars as pl # 构造示例数据 df = pl.DataFrame({ "col_1": [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], "col_2": [2, 4, 5, 7, 8, 10, 11, 13, 14, 16] }) window_size = 5 # 第一步:计算滚动窗口内的基础统计量 df_with_stats = df.with_columns([ pl.col("col_1").rolling(window_size).mean().alias("mean_x"), pl.col("col_2").rolling(window_size).mean().alias("mean_y"), (pl.col("col_1") * pl.col("col_2")).rolling(window_size).mean().alias("mean_xy"), (pl.col("col_1") ** 2).rolling(window_size).mean().alias("mean_x2"), (pl.col("col_2") ** 2).rolling(window_size).mean().alias("mean_y2") ]) # 第二步:代入公式计算滚动相关性 result_df = df_with_stats.with_columns( # 计算协方差 (pl.col("mean_xy") - pl.col("mean_x") * pl.col("mean_y")).alias("cov_xy"), # 计算x、y的标准差 (pl.col("mean_x2") - pl.col("mean_x") ** 2).sqrt().alias("std_x"), (pl.col("mean_y2") - pl.col("mean_y") ** 2).sqrt().alias("std_y") ).with_columns( # 计算相关系数,分母为0时自动返回NaN (pl.col("cov_xy") / (pl.col("std_x") * pl.col("std_y"))).alias("rolling_corr") ).drop(["mean_x", "mean_y", "mean_xy", "mean_x2", "mean_y2", "cov_xy", "std_x", "std_y"]) print(result_df)
可选参数调整
如果需要让窗口不足指定大小时也计算相关性(对应Pandas的min_periods参数),可以在rolling()中添加min_periods:
# 示例:窗口至少有2个数据点就计算 pl.col("col_1").rolling(window_size, min_periods=2).mean()
结果验证
你可以用原Pandas方法计算对比,两者结果完全一致(仅可能存在浮点精度差异):
import pandas as pd pd_df = df.to_pandas() pd_rolling_corr = pd_df['col_1'].rolling(5).corr(pd_df['col_2']) print(pd_rolling_corr)
内容的提问来源于stack exchange,提问作者Joris Medeišis
相关产品推荐
相关产品推荐

