news 2026/4/23 2:53:25

时间序列分析:平稳性检验方法与Python实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
时间序列分析:平稳性检验方法与Python实践

1. 时间序列平稳性检验的重要性

在时间序列分析中,平稳性是一个核心概念。与传统的分类和回归问题不同,时间序列数据具有时间依赖性,这意味着我们需要特别关注数据的统计特性是否随时间变化。

一个平稳的时间序列意味着其统计特性(如均值、方差等)不随时间变化。这种特性使得建模和预测变得更加可靠。相反,非平稳时间序列可能包含趋势、季节性或其他时间依赖性结构,这会使得传统统计方法失效。

提示:在实际应用中,大多数经济、金融和商业时间序列都是非平稳的,因此平稳性检验成为建模前的必要步骤。

2. 识别平稳与非平稳时间序列的直观方法

2.1 通过可视化初步判断

最直接的判断方法是绘制时间序列图。平稳时间序列的图形通常表现为围绕一个固定均值波动,而非平稳序列则可能显示出明显的趋势或季节性模式。

以"每日女性新生儿数量"数据集为例:

from pandas import read_csv from matplotlib import pyplot series = read_csv('daily-total-female-births.csv', header=0, index_col=0) series.plot() pyplot.show()

这个数据集显示出稳定的波动模式,没有明显的趋势或季节性,初步判断为平稳序列。

相比之下,"航空公司乘客数量"数据集:

series = read_csv('international-airline-passengers.csv', header=0, index_col=0) series.plot() pyplot.show()

这个数据集显示出明显的上升趋势和季节性波动,属于典型的非平稳序列。

2.2 统计量检验法

2.2.1 均值-方差分割检验

我们可以将时间序列分成两部分,比较两部分的统计特性:

X = series.values split = round(len(X) / 2) X1, X2 = X[0:split], X[split:] mean1, mean2 = X1.mean(), X2.mean() var1, var2 = X1.var(), X2.var()

对于平稳序列,两部分的均值和方差应该相近。例如女性新生儿数据:

mean1=39.76, mean2=44.19 variance1=49.21, variance2=48.71

而非平稳的航空公司乘客数据:

mean1=182.90, mean2=377.69 variance1=2244.09, variance2=7367.96
2.2.2 数据分布检验

检查数据是否符合正态分布也很重要,因为许多统计检验都基于这一假设:

series.hist() pyplot.show()

对于非正态分布的数据,可以考虑进行对数变换:

from numpy import log X = log(X) pyplot.hist(X) pyplot.show()

3. 统计检验方法:ADF检验

3.1 ADF检验原理

Augmented Dickey-Fuller (ADF)检验是最常用的平稳性检验方法。它检验的原假设是时间序列存在单位根(非平稳),备择假设是不存在单位根(平稳)。

检验结果包括:

  • ADF统计量:负值越大,越倾向于拒绝原假设(平稳)
  • p值:小于显著性水平(通常0.05)时拒绝原假设
  • 临界值:与ADF统计量比较

3.2 Python实现

对于女性新生儿数据:

from statsmodels.tsa.stattools import adfuller result = adfuller(X) print('ADF Statistic: %f' % result[0]) print('p-value: %f' % result[1]) print('Critical Values:') for key, value in result[4].items(): print('\t%s: %.3f' % (key, value))

输出:

ADF Statistic: -4.808291 p-value: 0.000052 Critical Values: 5%: -2.870 1%: -3.449 10%: -2.571

p值远小于0.05,强烈拒绝原假设,表明序列平稳。

对于航空公司乘客数据(原始数据):

ADF Statistic: 0.815369 p-value: 0.991880 Critical Values: 5%: -2.884 1%: -3.482 10%: -2.579

p值大于0.05,无法拒绝原假设,序列非平稳。

即使进行对数变换后:

ADF Statistic: -1.717017 p-value: 0.422367 Critical Values: 5%: -2.884 1%: -3.482 10%: -2.579

仍然无法拒绝原假设,说明对数变换不足以使该序列平稳。

4. 实际应用中的注意事项

4.1 检验方法的选择

  • 对于有明显趋势或季节性的数据,ADF检验可能不够敏感
  • 可以结合KPSS检验等其他方法进行综合判断
  • 对于高频金融数据,可能需要考虑ARCH效应

4.2 数据预处理

  • 对于非平稳数据,常用的处理方法包括:
    • 差分(消除趋势)
    • 季节差分(消除季节性)
    • 对数变换(稳定方差)
    • 分段平稳建模

4.3 模型选择

  • 对于平稳数据:可以直接使用AR、MA、ARMA等模型
  • 对于非平稳数据:可能需要使用ARIMA、SARIMA等模型
  • 对于波动聚集现象:考虑GARCH类模型

5. 常见问题与解决方案

5.1 ADF检验结果与图形判断不一致

可能原因:

  • 数据存在非线性趋势
  • 样本量不足
  • 存在结构性断点

解决方案:

  • 尝试更高阶差分
  • 增加样本量
  • 使用子样本检验

5.2 如何处理季节性非平稳

对于季节性数据:

  1. 先进行季节性差分
  2. 再进行常规差分
  3. 重新检验平稳性
# 季节性差分示例 diff = series.diff(12).dropna()

5.3 小样本数据的平稳性检验

小样本下ADF检验功效较低,可以:

  • 使用更严格的显著性水平
  • 结合自相关函数(ACF)和偏自相关函数(PACF)图形判断
  • 考虑使用滚动窗口检验

6. 进阶技巧与经验分享

6.1 自动化平稳性检验流程

在实际项目中,可以建立自动化检验流程:

def check_stationarity(series, max_diff=3): """自动检查序列平稳性并返回所需差分阶数""" for i in range(max_diff + 1): if i == 0: current = series.copy() else: current = current.diff().dropna() result = adfuller(current) if result[1] <= 0.05: print(f'序列在{i}阶差分后平稳') return i, current print('在最大差分阶数内未能使序列平稳') return None, None

6.2 滚动窗口平稳性检验

对于长时间序列,可以检查其局部平稳性:

def rolling_stationarity_test(series, window_size=100): """滚动窗口平稳性检验""" results = [] for i in range(len(series) - window_size + 1): window = series.iloc[i:i+window_size] p_value = adfuller(window)[1] results.append(p_value) pd.Series(results, index=series.index[window_size-1:]).plot() pyplot.axhline(0.05, color='red') pyplot.show()

6.3 多变量平稳性检验

对于多变量时间序列,需要考虑协整关系:

from statsmodels.tsa.vector_ar.vecm import coint_johansen def cointegration_test(series, det_order=0, k_ar_diff=1): """Johansen协整检验""" result = coint_johansen(series, det_order, k_ar_diff) print('特征值:', result.eig) print('临界值:', result.cvt) print('统计量:', result.lr1) return result

7. 实际案例分析

7.1 股票价格序列分析

股票价格通常是非平稳的,但收益率序列可能是平稳的:

# 获取股票数据 import yfinance as yf data = yf.download('AAPL', start='2020-01-01', end='2023-01-01') # 原始价格序列检验 result = adfuller(data['Close'].dropna()) print(f'价格序列p值: {result[1]:.4f}') # 通常>0.05 # 收益率序列检验 returns = data['Close'].pct_change().dropna() result = adfuller(returns) print(f'收益率序列p值: {result[1]:.4f}') # 通常<0.05

7.2 经济指标分析

以GDP数据为例,通常需要进行对数变换和差分:

# 假设gdp_series是GDP时间序列 log_gdp = np.log(gdp_series) dlog_gdp = log_gdp.diff().dropna() # 检验 print('原始GDP:', adfuller(gdp_series.dropna())[1]) print('对数GDP:', adfuller(log_gdp.dropna())[1]) print('对数差分GDP:', adfuller(dlog_gdp.dropna())[1])

8. 模型建立前的最后检查

在建立时间序列模型前,建议进行以下检查:

  1. 可视化检查:观察图形是否有明显趋势/季节性
  2. ACF/PACF检查:观察自相关函数衰减情况
  3. 统计检验:至少使用两种不同的平稳性检验方法
  4. 残差检查:对转换后的序列再次检验
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf def full_diagnostic(series): """完整的时间序列诊断""" # 可视化 series.plot() pyplot.show() # ACF/PACF plot_acf(series, lags=40) pyplot.show() plot_pacf(series, lags=40) pyplot.show() # 平稳性检验 print('ADF检验p值:', adfuller(series)[1]) # 正态性检验 print('Shapiro检验p值:', shapiro(series)[1])

9. 处理非平稳序列的实用方法

当确认序列非平稳时,可以考虑以下方法:

9.1 差分法

# 一阶差分 diff1 = series.diff().dropna() # 季节性差分(以12个月为例) seasonal_diff = series.diff(12).dropna()

9.2 变换法

常用变换包括:

  • 对数变换:np.log(series)
  • Box-Cox变换:from scipy.stats import boxcox
  • 标准化:(series - series.mean())/series.std()

9.3 分解法

使用季节性分解:

from statsmodels.tsa.seasonal import seasonal_decompose result = seasonal_decompose(series, model='multiplicative') result.plot() pyplot.show()

9.4 模型法

直接使用能处理非平稳数据的模型:

  • ARIMA:处理趋势
  • SARIMA:处理趋势和季节性
  • VAR:多变量非平稳序列

10. 总结与个人实践建议

时间序列平稳性检验是建模的基础步骤,但在实际应用中我发现:

  1. 不要过度依赖单一检验方法,应该结合多种方法和可视化分析
  2. 对于边界情况(如p值接近0.05),建议考虑不同差分阶数的影响
  3. 在金融时间序列中,即使序列平稳,也可能存在波动聚集效应
  4. 大数据场景下,考虑计算滚动平稳性可能更有意义

最后分享一个实用技巧:在Python中可以使用tsfresh包自动计算大量时间序列特征,包括各种平稳性指标:

from tsfresh import extract_features features = extract_features(pd.DataFrame({'id':1, 'time':range(len(series)), 'value':series}), column_id='id', column_sort='time')

这可以快速评估序列的多种统计特性,辅助平稳性判断。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 2:52:52

从‘隐式共享’到‘遍历优化’:一份给Qt/C++开发者的容器遍历避坑指南(含QVector、QList等)

从隐式共享到遍历优化&#xff1a;Qt容器高效遍历的底层逻辑与实战策略 在Qt框架的日常开发中&#xff0c;容器遍历是最基础却最容易踩坑的操作之一。许多开发者可能已经习惯了使用foreach或C11的范围for循环&#xff0c;但很少有人真正理解这些遍历方式背后Qt容器的隐式共享机…

作者头像 李华
网站建设 2026/4/23 2:50:23

从netCDF到Excel表格:手把手教你用Python批量提取并统计地表温度数据

从netCDF到Excel表格&#xff1a;Python自动化处理地表温度数据的完整指南 当气象学家拿到一组包含地表温度数据的netCDF文件时&#xff0c;往往需要从海量数据中提取关键信息。传统手动处理不仅耗时耗力&#xff0c;还容易出错。本文将展示如何用Python构建自动化流程&#xf…

作者头像 李华
网站建设 2026/4/23 2:46:23

Transformer模型在LHC实时触发系统中的优化与应用

1. 项目背景与核心挑战在大型强子对撞机&#xff08;LHC&#xff09;实验中&#xff0c;每25纳秒就会产生一次质子-质子碰撞&#xff0c;产生约1MB的原始数据。这意味着每秒会产生40TB的数据流——相当于每秒填满8000张DVD光盘。传统的触发系统采用两级过滤机制&#xff0c;其中…

作者头像 李华
网站建设 2026/4/23 2:43:50

Python数据分析实战:艾姆斯住房数据集描述性统计

1. 项目概述&#xff1a;用艾姆斯住房数据集揭开描述性统计的面纱当你第一次拿到一份陌生的数据集时&#xff0c;会不会有种面对茫茫数字海洋的无力感&#xff1f;三年前我刚接触数据分析时就深有体会。直到我发现了描述性统计这个"数据翻译器"&#xff0c;而艾姆斯住…

作者头像 李华
网站建设 2026/4/23 2:42:28

HarmonyOS 直播连麦实战:从开播端解码到看播端合流完整方案

场景与价值 连麦是直播中的一种常见场景&#xff0c;指两位及以上主播或主播与粉丝进行实时音视频交互&#xff0c;实现跨空间共同直播的模式&#xff0c;广泛应用于娱乐互动、电商带货、在线教育等领域。应用场景&#xff1a; 娱乐场景&#xff1a;主播PK、合唱互动&#xff0…

作者头像 李华