求助:基于滚动窗口对两个Pandas DataFrame执行多分析的实现方案
双DataFrame去趋势+滚动窗口自定义分析实现思路
一、先完成去趋势处理
去趋势的核心是移除数据中的线性/非线性趋势,以下两种方案可根据数据特征选择:
方案1:基于线性回归手动去趋势
适合明确存在线性趋势的数据,手动拟合回归线后减去趋势值:
import pandas as pd import numpy as np def detrend_linear(df): detrended_df = df.copy() for col in detrended_df.columns: x = np.arange(len(detrended_df[col])) # 拟合线性回归:y = a*x + b coeffs = np.polyfit(x, detrended_df[col], deg=1) trend = np.polyval(coeffs, x) # 减去趋势得到去后数据 detrended_df[col] = detrended_df[col] - trend return detrended_df # 对两个目标DataFrame执行去趋势 df1_detrended = detrend_linear(df1) df2_detrended = detrend_linear(df2)
方案2:用scipy的detrend函数快速实现
scipy内置函数支持线性/常数趋势移除,代码更简洁:
from scipy.signal import detrend def detrend_scipy(df): detrended_data = detrend(df.values, axis=0, type='linear') # axis=0按列处理 return pd.DataFrame(detrended_data, index=df.index, columns=df.columns) df1_detrended = detrend_scipy(df1) df2_detrended = detrend_scipy(df2)
关键注意点:去趋势后必须保留原索引,确保两个DataFrame的索引完全对齐,为后续滚动窗口同步分析提供基础。
二、同步滚动窗口应用自定义函数
核心是保证两个DataFrame的滚动窗口严格同步(同一时间段/位置的窗口数据),以下两种方式按需选择:
方式1:合并双DataFrame后批量滚动处理
若两个DataFrame列名无重复,可合并为多列DataFrame,自定义函数中拆分对应窗口数据:
# 合并去趋势后的两个df,添加前缀区分来源 combined_df = pd.concat([df1_detrended.add_prefix('df1_'), df2_detrended.add_prefix('df2_')], axis=1) # 自定义分析函数:输入窗口内的合并数据,返回计算结果 def custom_window_analysis(window_df): # 拆分出两个df的窗口数据 df1_window = window_df.filter(like='df1_').rename(columns=lambda x: x.replace('df1_', '')) df2_window = window_df.filter(like='df2_').rename(columns=lambda x: x.replace('df2_', '')) # 这里替换为你的实际业务逻辑,示例:计算两窗口数据的相关系数均值 example_result = df1_window.corrwith(df2_window).mean() return example_result # 应用滚动窗口:设置窗口大小,比如30 window_size = 30 rolling_results = combined_df.rolling(window=window_size).apply(custom_window_analysis)
方式2:遍历索引同步提取窗口数据
适合两个DataFrame结构差异大、合并不便的场景,手动对齐窗口位置:
window_size = 30 results = [] # 遍历每个窗口的起始索引 for i in range(len(df1_detrended) - window_size + 1): # 提取同一位置的窗口数据 df1_window = df1_detrended.iloc[i:i+window_size] df2_window = df2_detrended.iloc[i:i+window_size] # 执行自定义分析 res = custom_window_analysis(df1_window, df2_window) results.append(res) # 将结果转为Series,索引对应窗口的结束位置 rolling_results = pd.Series(results, index=df1_detrended.index[window_size-1:])
自定义函数适配:若用方式2,函数需接收两个参数:
def custom_window_analysis(df1_win, df2_win): # 示例:计算两窗口数据的逐列协方差均值 cov_matrix = np.cov(df1_win.T, df2_win.T) return cov_matrix.mean()
三、额外优化建议
- 若处理时间序列,优先用
rolling(window='30D')(按时间窗口)而非固定大小,更贴合业务逻辑; - 大数据量下,
apply效率较低,可尝试用numba加速自定义函数,或用Pandas内置向量化方法替代部分逻辑; - 先验证索引对齐:执行
assert df1_detrended.index.equals(df2_detrended.index),避免窗口错位。
内容的提问来源于stack exchange,提问作者may7even
相关产品推荐
相关产品推荐

