ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

时间序列分析入门:趋势与平稳性检验的原理、方法与实战

时间序列分析入门:趋势与平稳性检验的原理、方法与实战 1. 从数据到洞察时序分析为何始于“检验”在数据分析的众多分支里时序分析总是带着一种独特的魅力。它处理的不是一堆孤立的、可以随意打乱顺序的样本点而是一条流淌着的时间线。无论是金融市场的股价波动、气象站记录的每日温度、还是工厂传感器传回的设备振动信号这些数据都承载着时间的烙印。当我们拿到这样一份数据第一反应往往是画图、计算指标甚至直接套用复杂的预测模型。但一个经常被忽略却至关重要的前置步骤是先理解你手中这条时间序列的“脾气秉性”。这就引出了我们今天的核心话题趋势性检验与平稳性检验。你可以把它们看作是给时序数据做一次全面的“体检”。趋势性检验回答的是“这条时间线整体是在向上爬升、向下滑落还是基本保持水平”而平稳性检验则更深入一层它要判断“这条时间线在不同时间段的统计特性如均值、方差是否稳定不变”。这两个问题的答案直接决定了后续所有分析方法的基石是否牢固。为什么这个“体检”如此关键想象一下你发现过去五年的月销售额数据有明显的上升趋势。如果你无视这个趋势直接计算一个固定的平均值来预测未来结果必然会严重偏低。再比如许多经典的时间序列预测模型如自回归移动平均模型其理论前提就是数据必须是平稳的。如果数据不平稳例如均值随时间漂移强行使用这些模型得到的预测结果不仅不准确其统计推断如置信区间也完全失效相当于用错误的公式去解一道题。因此趋势性检验和平稳性检验绝非可有可无的“花架子”而是建模前必须完成的“规定动作”。它们帮助我们规避误用模型的陷阱引导我们选择正确的分析路径——是应该先剔除趋势还是进行差分处理这直接关系到整个数学建模项目的成败与效率。接下来我们就深入这两个检验的核心看看具体如何操作以及背后那些容易踩坑的细节。2. 趋势性检验捕捉时间序列的长期走向当我们谈论时间序列的趋势时指的是数据在较长时期内所呈现出的持续向上或向下的运动。这种趋势可能源于长期的经济增长、技术的进步、季节的累积效应或者某种不可逆的系统性变化。识别趋势是建模的第一步因为趋势成分通常会掩盖数据中更细微的周期或随机波动并且许多分析方法要求先将趋势分离出去。2.1 视觉诊断法最直观的起点在动用任何统计检验之前最朴素也最有效的方法是绘制时序图。将时间放在横轴观测值放在纵轴用线图连接起来。操作与解读绘制图形使用任何你熟悉的工具Python的Matplotlib/SeabornR的ggplot2甚至Excel生成时序图。整体观察不要急于下结论。观察整条曲线的整体形态。是一条大致倾斜的直线还是一条弯曲的曲线是单调上升/下降还是在某个时间点发生了趋势的转折辅助线可以在图中添加一条移动平均线例如12期移动平均用于月度数据或局部回归平滑线如LOESS。这些平滑后的曲线能有效过滤短期波动让长期趋势更加清晰可见。注意视觉诊断高度依赖于主观判断且容易受到极端值或短期剧烈波动的影响。它适合作为初步探索但不能作为最终的统计依据。特别是当趋势比较微弱或非线性时肉眼很难做出准确判断。2.2 Mann-Kendall趋势检验非参数方法的稳健之选当我们需要一个定量的、统计上严谨的结论时Mann-KendallM-K检验是一个极佳的选择。它是一种非参数检验不要求数据服从特定的分布如正态分布对异常值也不敏感非常适合实际中那些分布未知、可能存在离群点的数据。核心原理 M-K检验的核心思想是检验序列的顺序关系。它计算所有可能的数据对(X_i, X_j), i j查看后一个值X_j是否大于前一个值X_i。通过统计这种“增长”对和“减少”对的数量差来判断趋势是否存在。计算统计量 S 定义S Σ_{i1}^{n-1} Σ_{ji1}^{n} sgn(X_j - X_i)。 其中sgn()是符号函数如果X_j X_isgn 1如果X_j X_isgn 0如果X_j X_isgn -1方差与标准化 在无趋势的原假设下统计量S的期望值为0。其方差Var(S)的计算考虑了可能存在的数据结即重复值。最终将S标准化得到Z统计量Z (S - sgn(S)) / sqrt(Var(S))。这个Z统计量在大样本下近似服从标准正态分布。假设检验原假设 H0序列无趋势。备择假设 H1序列存在单调趋势可以是上升或下降通过S或Z的符号判断。判断计算Z值对应的p值。如果p值小于显著性水平如0.05则拒绝原假设认为存在显著趋势。Z值为正表示上升趋势为负表示下降趋势。Python实操示例使用pymannkendall库import pymannkendall as mk import numpy as np # 假设我们有一组年度平均温度数据 yearly_temp np.array([15.2, 15.5, 15.3, 15.8, 16.1, 16.0, 16.4, 16.7, 16.5, 17.0]) # 执行Mann-Kendall检验 result mk.original_test(yearly_temp) print(result)输出会包含趋势方向increasing/decreasing、p值、Z统计量等。如果result.trend为 ‘increasing‘ 且result.p 0.05则表明存在显著的上升趋势。实操心得样本量M-K检验需要一定的样本量才能保证功效。通常建议n10。对于非常短的时间序列结果可能不可靠。季节性影响如果数据有强烈的季节性如月度销售数据直接对原始数据做M-K检验可能会把季节性波动误判为趋势。正确的做法是先提取年度数据如每年一个值或对原始数据进行“去季节化”处理后再检验。突变点标准的M-K检验假设趋势在整个序列中是单调的。如果序列中存在趋势突变点例如政策改变前后的数据标准M-K检验可能无法准确识别。此时需要考虑使用改进的M-K检验如序列均一性检验或滑动窗口M-K检验。2.3 Cox-Stuart趋势检验针对小样本的快速判断Cox-Stuart检验是另一种非参数方法它比M-K检验更简单直接特别适用于小样本数据。核心原理 将序列分成前后两半如果数据点数为奇数则去掉中间一个点。然后配对比较前半部分和后半部分对应位置的数据点。统计前半部分数据点大于后半部分对应数据点的对数记为S以及小于的对数记为S-。趋势的强度由S和S-的差异来判断。假设检验原假设 H0无趋势。备择假设 H1存在趋势。判断取S max(S, S-)。在无趋势的原假设下S应服从二项分布。通过查二项分布表或计算p值可以判断趋势是否显著。适用场景与局限 Cox-Stuart检验计算极快对数据分布没有要求。但其缺点也很明显它只利用了序列首尾的信息完全忽略了中间数据点的顺序和波动因此信息利用不充分检验功效通常低于M-K检验。它更适合作为对M-K检验结果的一个快速验证或补充或者在数据量极少时的初步筛查。3. 平稳性检验审视统计特性的时间不变性平稳性是时间序列分析中一个基石性的概念。一个平稳的时间序列其统计性质如均值、方差、自协方差不随时间推移而改变。这意味着序列的行为在时间上是“一致”的我们可以用历史数据来推断未来的统计规律。绝大多数经典时序模型AR, MA, ARMA都建立在平稳序列的假设之上。3.1 平稳性的定义与类型在深入检验之前我们需要明确两种主要的平稳性严平稳序列的任意有限维联合分布不随时间平移而改变。这是一个非常强的条件在实际中难以验证和应用。弱平稳宽平稳这是我们通常检验和要求的类型。它要求均值平稳序列的期望值E(X_t)是一个常数与时间t无关。方差平稳序列的方差Var(X_t)是一个常数与时间t无关。自协方差平稳序列在任意两个时刻t和tk的协方差Cov(X_t, X_{tk})只依赖于时间间隔k而与具体的起始时间t无关。简而言之弱平稳序列围绕一个恒定均值上下波动且波动的幅度和模式自相关结构在时间上是稳定的。直观上看它的时序图应该在一个水平线附近波动没有明显的趋势或周期。3.2 Augmented Dickey-Fuller (ADF) 检验最常用的单位根检验ADF检验是检验平稳性的“黄金标准”。它的核心思想是检验序列是否存在“单位根”。如果存在单位根则序列是非平稳的通常具有随机游走的特性反之则可能是平稳的。模型基础 ADF检验基于以下回归模型Δy_t α βt γy_{t-1} Σ_{i1}^{p} φ_i Δy_{t-i} ε_t其中Δy_t y_t - y_{t-1}即一阶差分。α是常数项漂移项。βt是时间趋势项。γy_{t-1}是核心项γ ρ - 1ρ是自回归系数。Σ φ_i Δy_{t-i}是加入的滞后差分项用于消除误差项的自相关确保其是白噪声。ε_t是白噪声误差项。假设检验原假设 H0γ 0即序列存在单位根非平稳。备择假设 H1γ 0即序列不存在单位根平稳。检验统计量与判断 ADF检验会计算一个特定的t统计量与常规的t统计量不同然后将其与一系列临界值由Dickey和Fuller通过模拟得到进行比较。我们通常直接关注p值如果p值小于显著性水平如0.05则拒绝原假设认为序列平稳。如果p值大于显著性水平则无法拒绝原假设认为序列非平稳。Python实操示例使用statsmodels库from statsmodels.tsa.stattools import adfuller import pandas as pd # 假设我们有一组存在明显上升趋势的模拟数据 np.random.seed(42) trend_data pd.Series(np.arange(100) * 0.5 np.random.randn(100) * 10) # 执行ADF检验 autolag‘AIC‘ 表示自动根据AIC准则选择最佳滞后阶数p adf_result adfuller(trend_data, autolag‘AIC‘) print(‘ADF Statistic: %f‘ % adf_result[0]) print(‘p-value: %f‘ % adf_result[1]) print(‘Critical Values:‘) for key, value in adf_result[4].items(): print(‘\t%s: %.3f‘ % (key, value)) # 判断 if adf_result[1] 0.05: print(“序列是平稳的拒绝原假设”) else: print(“序列是非平稳的无法拒绝原假设”)对于这个有明显趋势的数据p值几乎肯定会大于0.05输出非平稳的结论。关键参数与实操陷阱回归模型类型regressionadfuller函数有一个regression参数通常有‘c‘仅常数项、‘ct‘常数项和趋势项、‘ctt‘常数项、线性和二次趋势项、‘nc‘无常数无趋势。如何选择一个实用的方法是先观察时序图。如果序列看起来围绕非零均值波动用‘c‘如果看起来有线性趋势用‘ct‘。选择不当会影响检验功效。一个保守的做法是从包含趋势项的模型‘ct‘开始。滞后阶数lags滞后阶数p的选择至关重要。p太小残差中可能仍有自相关导致检验失真p太大会损失自由度降低检验功效。设置autolag‘AIC‘或‘BIC‘让函数自动选择是一个好习惯。结果解读ADF检验的“无法拒绝原假设”并不意味着序列一定是非平稳的也可能是检验功效不足例如样本量太小、趋势不明显。此时需要结合其他检验如KPSS综合判断。3.3 KPSS检验从另一视角验证平稳性KPSS检验与ADF检验的假设正好相反它为我们提供了另一个重要的视角。假设检验原假设 H0序列是趋势平稳或水平平稳的。备择假设 H1序列是非平稳的存在单位根。核心思想 KPSS检验将序列分解为确定性趋势、随机游走和稳态误差三部分。它构造一个LM统计量来检验随机游走分量的方差是否为0。如果为0则序列是趋势平稳的围绕一个确定性趋势波动如果不为0则存在非平稳的随机游走成分。如何与ADF检验结合使用 这是实践中非常有效的“组合拳”情况一ADF检验拒绝原假设平稳且KPSS检验不拒绝原假设平稳。结论最强序列是平稳的。情况二ADF检验不拒绝原假设非平稳且KPSS检验拒绝原假设非平稳。结论最强序列是非平稳的。情况三两个检验结论矛盾。这是最常见也最需要小心的情况。通常意味着序列可能具有接近单位根的特性或者存在结构突变。此时需要更仔细地分析时序图或进行差分后再检验。Python实操示例from statsmodels.tsa.stattools import kpss # 对同一组趋势数据做KPSS检验 kpss_result kpss(trend_data, regression‘ct‘) # ‘ct‘表示检验“趋势平稳”的原假设 print(‘KPSS Statistic: %f‘ % kpss_result[0]) print(‘p-value: %f‘ % kpss_result[1]) print(‘Critical Values:‘) for key, value in kpss_result[3].items(): print(‘\t%s: %.3f‘ % (key, value)) # KPSS检验的p值判断与ADF相反p值小则拒绝原假设认为非平稳 if kpss_result[1] 0.05: print(“序列是非平稳的拒绝原假设”) else: print(“序列是平稳的无法拒绝原假设”)对于趋势数据KPSS检验的p值很可能很小拒绝“趋势平稳”的原假设得出非平稳的结论与ADF检验相互印证。3.4 其他辅助诊断方法除了正式的统计检验还有一些图形化方法可以帮助我们判断平稳性自相关图ACF Plot平稳序列的自相关函数通常会快速衰减至0或在一定滞后阶数后落入置信区间内。而非平稳序列的自相关函数衰减非常缓慢在很大滞后阶数上仍然显著不为0。在Python中可以使用statsmodels.graphics.tsaplots.plot_acf来绘制。滚动统计量图计算并绘制序列的滚动均值如30期滚动平均和滚动标准差。如果序列是平稳的这两条线应该大致是水平的直线。如果滚动均值有明显的变化趋势或滚动标准差剧烈波动则提示非平稳。这是非常直观的验证方法。4. 检验后的行动指南从诊断到处理完成了趋势性和平稳性检验我们得到了关于数据特性的诊断报告。接下来就需要根据诊断结果采取相应的数据预处理措施为后续建模铺平道路。这个决策流程至关重要。4.1 诊断结果与处理路径决策我们可以将诊断结果归纳为以下几种典型情况并给出对应的处理建议诊断情况趋势性检验平稳性检验 (ADF/KPSS)数据特征判断推荐处理路径情况A存在显著趋势非平稳典型的趋势非平稳序列1. 差分处理。一阶差分通常可消除线性趋势。差分后需重新检验平稳性。2. 趋势拟合与剔除。用回归模型拟合趋势项然后从原序列中减去。情况B无显著趋势非平稳可能是随机游走或方差非平稳1. 差分处理。尝试一阶差分。2. 检查方差。绘制滚动标准差图若方差变化大可能需进行对数变换或Box-Cox变换稳定方差再检验平稳性。情况C存在显著趋势平稳趋势平稳序列1. 直接去趋势。由于序列围绕一个确定性趋势波动可直接用回归提取趋势成分剩余部分为平稳序列。2. 使用包含趋势项的模型。如ARIMA模型中的drift项。情况D无显著趋势平稳弱平稳序列理想情况。无需特殊处理可直接用于ARMA等经典平稳时间序列模型建模。4.2 核心处理技术详解1. 差分法差分是处理趋势和非平稳性最常用、最有效的方法之一。一阶差分可以消除线性趋势二阶差分可以消除二次曲线趋势。操作y_t‘ y_t - y_{t-1}一阶差分。在Pandas中使用series.diff().dropna()。注意事项差分会损失一个数据点。过度差分阶数过高会使序列产生不必要的波动并可能导致模型不可逆。通常差分阶数不超过2。差分后必须重新进行平稳性检验确保序列已转化为平稳。2. 趋势拟合法当趋势具有明确的函数形式如线性、多项式、指数时可以直接拟合并剔除。操作以线性趋势为例用最小二乘法拟合模型y_t β0 β1 * t ε_t。然后得到去趋势后的序列ε_t y_t - (β0 β1 * t)。优缺点优点是可解释性强能保留趋势的具体形式。缺点是假设了趋势的特定形态如果假设错误剔除效果会变差。3. 变换法对于方差非平稳异方差的序列即波动幅度随时间变化可以通过数学变换稳定方差。对数变换y‘_t log(y_t)。适用于序列值均为正且其波动幅度与水平成正比的情况例如金融价格序列。Box-Cox变换更通用的幂变换族公式为y‘_t (y_t^λ - 1)/λ (λ≠0)或log(y_t) (λ0)。参数λ通过最大似然估计确定。Python中可用scipy.stats.boxcox。实操心得顺序很重要一个标准的预处理流程往往是先处理方差非平稳如做对数变换再检验并处理趋势和均值非平稳如差分。因为变换可能改变序列的趋势形态先做变换能让后续的趋势判断更准确。处理完成后务必再次进行平稳性检验确保目标达成。5. 综合案例实战全球气温数据分析让我们用一个接近真实的案例串联起从检验到处理的完整流程。假设我们有一份1880年至2023年的全球年平均气温异常数据相对于20世纪平均值的偏差。5.1 数据初探与可视化首先我们加载数据并绘制时序图。import pandas as pd import matplotlib.pyplot as plt import numpy as np from statsmodels.tsa.stattools import adfuller, kpss import pymannkendall as mk # 假设数据已加载到DataFrame df 中包含‘Year‘和‘Temp_Anomaly‘两列 # 绘制时序图 plt.figure(figsize(12, 6)) plt.plot(df[‘Year‘], df[‘Temp_Anomaly‘], marker‘.‘) plt.xlabel(‘Year‘) plt.ylabel(‘Temperature Anomaly (°C)‘) plt.title(‘Global Annual Temperature Anomaly (1880-2023)‘) plt.grid(True, linestyle‘--‘, alpha0.7) plt.show()从图上我们可以直观地看到序列整体呈现明显的上升趋势且波动似乎随着时间的推移有所增大后期波动更剧烈。5.2 执行趋势性与平稳性检验步骤1Mann-Kendall趋势检验result_mk mk.original_test(df[‘Temp_Anomaly‘]) print(f“Mann-Kendall Test:“) print(f“ Trend: {result_mk.trend}“) print(f“ p-value: {result_mk.p:.6f}“) print(f“ Z-statistic: {result_mk.z:.3f}“)输出结果几乎可以肯定显示Trend: increasing且p-value: 0.000000证实存在极其显著的上升趋势。步骤2ADF平稳性检验包含趋势项adf_result adfuller(df[‘Temp_Anomaly‘], regression‘ct‘, autolag‘AIC‘) print(f“\nADF Test (with trend):“) print(f“ ADF Statistic: {adf_result[0]:.3f}“) print(f“ p-value: {adf_result[1]:.6f}“) # 判断 if adf_result[1] 0.05: print(“ Conclusion: Fail to reject H0 - Series is NON-STATIONARY“)由于存在强趋势ADF检验的p值很可能大于0.05得出非平稳的结论。步骤3KPSS平稳性检验检验趋势平稳的原假设kpss_result kpss(df[‘Temp_Anomaly‘], regression‘ct‘) print(f“\nKPSS Test (for trend-stationarity):“) print(f“ KPSS Statistic: {kpss_result[0]:.3f}“) print(f“ p-value: {kpss_result[1]:.6f}“) # 判断 (KPSS的p值小则拒绝平稳原假设) if kpss_result[1] 0.05: print(“ Conclusion: Reject H0 - Series is NON-STATIONARY“)KPSS检验也很可能因为明显的趋势而拒绝“趋势平稳”的原假设得出非平稳结论。诊断小结数据存在显著上升趋势M-K检验且同时被ADF和KPSS检验判定为非平稳。这符合我们表格中的情况A趋势非平稳。5.3 数据处理与再检验步骤1尝试一阶差分消除趋势# 计算一阶差分 df[‘Temp_Diff‘] df[‘Temp_Anomaly‘].diff().dropna() # 绘制差分后序列 plt.figure(figsize(12, 6)) plt.plot(df[‘Year‘].iloc[1:], df[‘Temp_Diff‘]) plt.axhline(y0, color‘r‘, linestyle‘-‘, alpha0.3) plt.xlabel(‘Year‘) plt.ylabel(‘First Difference (°C)‘) plt.title(‘Global Temperature Anomaly - First Difference‘) plt.grid(True, linestyle‘--‘, alpha0.7) plt.show()差分后的序列图应该围绕0值上下波动不再有明显的趋势。步骤2对差分后序列进行平稳性检验# ADF检验差分后通常只带常数项即可 adf_result_diff adfuller(df[‘Temp_Diff‘].dropna(), regression‘c‘, autolag‘AIC‘) print(f“ADF Test on Differenced Series:“) print(f“ p-value: {adf_result_diff[1]:.6f}“) if adf_result_diff[1] 0.05: print(“ Conclusion: Reject H0 - Differenced series is STATIONARY“) # KPSS检验检验水平平稳 kpss_result_diff kpss(df[‘Temp_Diff‘].dropna(), regression‘c‘) print(f“\nKPSS Test on Differenced Series:“) print(f“ p-value: {kpss_result_diff[1]:.6f}“) if kpss_result_diff[1] 0.05: print(“ Conclusion: Fail to reject H0 - Differenced series is STATIONARY“)此时ADF检验的p值应变得很小0.05拒绝原假设KPSS检验的p值应变得较大0.05无法拒绝原假设。两者一致表明一阶差分后的序列是平稳的。步骤3可选处理可能存在的方差非平稳观察原始序列图后期波动似乎更大。我们可以计算滚动标准差来验证。rolling_std df[‘Temp_Anomaly‘].rolling(window30).std() plt.figure(figsize(12, 4)) plt.plot(df[‘Year‘], rolling_std) plt.xlabel(‘Year‘) plt.ylabel(‘30-year Rolling Std Dev‘) plt.title(‘Rolling Standard Deviation of Temperature Anomaly‘) plt.grid(True, linestyle‘--‘, alpha0.7) plt.show()如果滚动标准差显示明显上升趋势说明存在异方差。可以考虑先对原始数据做对数变换由于温度异常值有正有负需先平移使其全为正然后再进行差分和检验。但在本例中气温异常值的波动增长可能并非指数型简单的差分可能已足够使序列平稳用于建模。这是一个需要根据模型后续表现来权衡的建模选择。5.4 案例总结与建模指引通过这个完整流程我们得出结论原始全球气温异常序列是趋势非平稳的。一阶差分能有效将其转化为平稳序列。因此在后续建立ARIMA等模型时差分阶数d应设置为1。这个“d1”的参数不是凭空猜测的而是由严格的趋势性与平稳性检验推导出的科学依据。如果进一步分析发现差分后序列的自相关图和偏自相关图具有截尾或拖尾特征我们就可以 confidently 进入ARIMA(p,1,q)模型的定阶与参数估计阶段。整个建模流程的基石由此奠定。忽视检验而直接建模很可能选择一个不合适的d值导致模型识别错误、预测失效。这个案例清晰地展示了在时间序列分析的起点上投入时间进行严谨的“数据体检”是多么重要的一步。它节省的不是几分钟而是可能浪费在错误方向上的数天甚至数周时间。
返回列表