You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas大DataFrame下,如何高效计算滚动1000行的相关矩阵?

问题描述

我有一个大型DataFrame,所有列的值均为浮点数,索引为DatetimeIndex类型,示例数据如下:

col0 col1 col2 col3 col4 ...
2035-10-30  1.0  1.0  1.0  1.0  1.0 ...   
2035-10-31  1.0  1.0  1.0  1.0  1.0 ...
2035-11-01  1.0  1.0  1.0  1.0  1.0 ...
2035-11-02  1.0  1.0  1.0  1.0  1.0 ...
    ...     ...  ...  ...  ...  ... ...

需要针对每个索引(即每个日期),计算DataFrame最后1000行的相关矩阵,当前使用的循环代码如下:

for d in df.index:
    cor_mat = other_df[:d].tail(1000).corr()

其中df与other_df的维度和索引完全一致。由于DataFrame规模庞大,当前实现速度极慢。尝试过使用.rolling()方法但未成功,请问如何通过向量化操作或其他方式优化该过程?

优化方案

直接循环计算每个窗口的相关矩阵效率极低,核心原因是重复计算了大量数据的统计量。可以利用滚动窗口的均值、协方差推导相关系数,完全用向量化操作实现,避免循环。

步骤1:计算滚动窗口的均值

先对other_df的每一列计算窗口大小为1000的滚动均值:

rolling_mean = other_df.rolling(window=1000, min_periods=1).mean()

min_periods=1用于处理窗口不足1000行的初始阶段(比如前999天),如果不需要保留这些初始值,可去掉该参数,此时前999行结果为NaN。

步骤2:计算滚动窗口的协方差矩阵

先计算每个元素减去对应窗口的均值,得到中心化数据:

centered = other_df - rolling_mean

再通过矩阵乘法结合滚动求和计算协方差矩阵:

import numpy as np

n_cols = other_df.shape[1]
# 初始化三维数组存储每个窗口的协方差矩阵,形状为(行数, 列数, 列数)
cov_matrices = np.zeros((len(other_df), n_cols, n_cols))

# 遍历列对计算滚动协方差
for i in range(n_cols):
    for j in range(i, n_cols):
        # 计算偏差乘积的滚动和,除以窗口大小-1得到无偏协方差
        cov = centered.iloc[:, i].mul(centered.iloc[:, j]).rolling(window=1000, min_periods=1).sum() / (other_df.rolling(window=1000, min_periods=1).count().iloc[:, 0] - 1)
        cov_matrices[:, i, j] = cov.values
        cov_matrices[:, j, i] = cov.values  # 协方差矩阵对称

步骤3:从协方差矩阵推导相关矩阵

相关系数等于协方差除以两个变量的标准差乘积,先计算每列的滚动标准差:

rolling_std = other_df.rolling(window=1000, min_periods=1).std()

再遍历每个窗口计算相关矩阵:

cor_matrices = np.zeros_like(cov_matrices)

for idx in range(len(other_df)):
    std = rolling_std.iloc[idx].values
    std_outer = np.outer(std, std)
    # 避免除以0,标准差为0时相关系数设为1(自身相关)或0(按需调整)
    mask = std_outer != 0
    cor_matrices[idx][mask] = cov_matrices[idx][mask] / std_outer[mask]
    np.fill_diagonal(cor_matrices[idx], 1.0)  # 对角线元素强制为1

步骤4:获取指定日期的相关矩阵

cor_matrices的第idx个元素,就是other_df截至other_df.index[idx]的最后1000行的相关矩阵,可直接按df的索引位置对应取值。

额外优化:Numba加速循环

如果列数较多,可用Numba编译协方差计算的循环,进一步提升速度:

from numba import njit

@njit
def compute_cov_matrices(centered_vals, window_size, min_periods):
    n_rows, n_cols = centered_vals.shape
    cov_matrices = np.zeros((n_rows, n_cols, n_cols))
    for i in range(n_cols):
        for j in range(i, n_cols):
            col_i = centered_vals[:, i]
            col_j = centered_vals[:, j]
            product = col_i * col_j
            for row in range(n_rows):
                start = max(0, row - window_size + 1)
                count = row - start + 1
                if count < min_periods:
                    cov = np.nan
                else:
                    sum_prod = product[start:row+1].sum()
                    cov = sum_prod / (count - 1)
                cov_matrices[row, i, j] = cov
                cov_matrices[row, j, i] = cov
    return cov_matrices

# 转换为numpy数组传入函数
centered_vals = centered.values
cov_matrices = compute_cov_matrices(centered_vals, 1000, 1)

内容的提问来源于stack exchange,提问作者DataScienceNovice

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 19:42:36