如何在Python中对DataFrame rolling.corr生成的每个窗口相关系数表求和并绘制时间序列图
Python实现滚动窗口相关性求和并绘制时间序列图
针对你需要实现的类似MATLAB的滚动窗口相关系数求和功能,我整理了以下解决方案,完美匹配你的需求:
步骤解析
首先你已经用df.rolling(5).corr(pairwise=True)得到了每个窗口的相关系数矩阵,接下来需要:
- 对每个窗口的相关矩阵求和,剔除对角线固定为1的元素(每列对应一个1,共
n个,n是数据列数) - 将结果整理为时间序列并绘图
完整实现代码
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 你的示例数据 d = {'col1': [-2587.944231, -1897.324231,-2510.304231,-2203.814231,-2105.734231,-2446.964231,-2963.904231,-2177.254231, 2796.354231,-2085.304231], 'col2': [-3764.468462,-3723.608462,-3750.168462,-3694.998462,-3991.268462,-3972.878462,3676.608462,-3827.808462,-3629.618462,-1841.758462,], 'col3': [-166.1357692,-35.36576923, 321.4157692,108.9257692,-123.2257692, -10.84576923, -100.7457692, 89.27423077, -211.0857692, 101.5342308]} df = pd.DataFrame(data=d) # 步骤(a): 计算窗口大小为5的滚动相关系数 dfn = df.rolling(5).corr(pairwise=True) # 步骤(b): 对每个窗口的相关矩阵求和并剔除对角线的1 n_cols = df.shape[1] # 列数,即对角线1的数量 # 按窗口索引分组,计算每个组的总和并减去对角线的1 cact = dfn.groupby(level=0).apply(lambda mat: mat.values.sum() - n_cols) # 移除前4个无结果的窗口(窗口大小5,前4个索引不够数据) cact = cact.dropna().reset_index(drop=True) # 绘制时间序列图(类似MATLAB效果) plt.figure(figsize=(10, 6)) plt.plot(cact, marker='o', linestyle='-', color='tab:blue') plt.title('Rolling Window Correlation Sum (Excluding Diagonal 1s)') plt.xlabel('Time Step') plt.ylabel('Sum of Non-Diagonal Correlation Coefficients') plt.grid(alpha=0.3) plt.show()
代码说明
- 分组处理相关矩阵:
dfn是多层索引的DataFrame,第一层是窗口结束的索引,用groupby(level=0)可以精准获取每个窗口对应的完整相关系数矩阵。 - 求和与剔除对角线:
mat.values.sum()计算矩阵所有元素的和,减去n_cols(对角线1的数量),得到的就是所有传感器两两之间相关系数的总和。 - 绘图细节:
dropna()移除前4个无效窗口(因为窗口大小为5,从第5个数据点开始才有有效结果),绘图时添加标记点和网格,和MATLAB的可视化风格对齐。
替代实现方式(更高效的数组操作)
如果你的数据集非常大,用三维数组操作会更高效:
n_cols = df.shape[1] # 将滚动相关结果转换为三维数组:(窗口数, 列数, 列数) corr_arrays = dfn.values.reshape(-1, n_cols, n_cols) # 求和并剔除对角线 cact = corr_arrays.sum(axis=(1,2)) - n_cols # 过滤无效的NaN结果 cact = cact[~np.isnan(cact)]
这个方法和上面的groupby结果完全一致,但处理大型数据时速度更快。
内容的提问来源于stack exchange,提问作者ultruction
相关产品推荐
相关产品推荐

