如何解决statsmodels库grangercausalitytests方法中的"非平稳时间序列"错误?

一、问题现象与诊断

当使用statsmodels.tsa.stattools.grangercausalitytests()方法时,最常见的错误之一是遇到非平稳时间序列导致的检验失效。系统通常会抛出类似"ValueError: The test requires stationary variables"的错误提示。Granger因果检验的基本假设要求输入的时间序列数据必须满足弱平稳性条件,即均值、方差和自相关结构不随时间变化。

二、根本原因分析

时间序列的非平稳性主要来源于三种典型特征:

  • 趋势成分:序列呈现明显的上升或下降趋势
  • 季节性波动:周期性出现的规律性波动
  • 结构突变:均值或方差的突然跳变

这些特征会导致伪回归问题,使Granger检验结果出现统计显著性偏差。通过ADF检验(Augmented Dickey-Fuller test)可以量化评估序列的平稳性,其零假设为序列存在单位根(非平稳)。

三、五种解决方案详解

3.1 差分转换法

from statsmodels.tsa.stattools import adfuller
import numpy as np

def make_stationary(series, max_diff=3):
    for i in range(max_diff):
        p_value = adfuller(series)[1]
        if p_value < 0.05:
            return series, i
        series = np.diff(series)
    raise ValueError("Series cannot be made stationary")

3.2 对数变换处理

对于存在指数趋势异方差性的序列,可采用对数变换:

log_series = np.log(original_series + 1e-10)

3.3 季节性分解

使用STL分解移动平均法分离趋势和季节成分:

from statsmodels.tsa.seasonal import STL
stl = STL(series, period=12)
res = stl.fit()
stationary_series = res.resid

3.4 滚动标准化

通过滚动窗口计算均值和标准差:

rolling_mean = series.rolling(window=12).mean()
rolling_std = series.rolling(window=12).std()
normalized = (series - rolling_mean) / rolling_std

3.5 协整检验

当多变量序列存在共同趋势时,可进行Johansen协整检验

from statsmodels.tsa.vector_ar.vecm import coint_johansen
result = coint_johansen(data, det_order=0, k_ar_diff=1)

四、最佳实践建议

推荐采用以下工作流程

  1. 可视化检查序列的自相关图(ACF)和偏自相关图(PACF)
  2. 执行ADF检验KPSS检验双重验证
  3. 根据数据特性选择适当的转换方法
  4. 转换后重新检验平稳性
  5. 最后进行Granger因果检验