尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

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

时序分析入门:趋势与平稳性检验的核心原理与Python实战

时序分析入门:趋势与平稳性检验的核心原理与Python实战 1. 项目概述从数据到洞察时序分析的两大基石拿到一份时间序列数据比如过去十年的月度销售额、某城市每日的PM2.5浓度、或者某个服务器每小时的CPU负载我们第一反应往往是画个折线图看看走势。但作为一名数据分析师或建模者我们不能只停留在“看”的层面。时序数据分析的核心在于从看似杂乱无章、上下波动的曲线中提炼出确定性的规律并识别出随机性的成分为后续的预测、控制或决策提供坚实的依据。而这一切的起点就是两个至关重要的“体检”项目趋势性检验和平稳性检验。这就像是给数据做一次全面的健康检查判断它是否有长期的发展方向趋势以及其内在的统计特性是否稳定平稳。只有明确了这些基本属性我们才能选择合适的模型“对症下药”否则用错了模型预测结果可能会南辕北辙。我处理过不少时序项目踩过最深的坑之一就是拿到数据后看到有明显的上升或下降形态就迫不及待地套用ARIMA模型进行预测结果模型拟合看似不错但预测效果一塌糊涂。后来复盘才发现数据中存在强烈的非线性趋势而我没有先进行严格的趋势性检验和平稳性检验直接默认数据是平稳的或者用简单的差分处理导致模型根本抓不住数据的真实结构。所以今天我想结合自己的实操经验把这“两大检验”的来龙去脉、方法选择、操作步骤和避坑要点系统地梳理一遍。无论你是刚开始接触数学建模的学生还是需要在工作中分析业务指标的数据分析师理解并掌握这两项检验都能让你在时序分析的道路上避开很多初级错误建立起可靠的第一道防线。2. 核心概念解析趋势与平稳究竟在说什么在深入检验方法之前我们必须把概念本身吃透。很多朋友容易混淆“趋势”和“非平稳”其实它们既有联系又有区别。2.1 趋势性数据长期运动的“方向盘”趋势指的是时间序列在长期内表现出的一种持续的、单向的上升或下降的运动方向。它反映了数据在较长时期内的基本发展态势。比如随着经济发展和消费升级一个品牌的年销售额可能呈现长期的线性增长趋势又比如随着节能技术的普及某地区的单位GDP能耗可能呈现长期的下降趋势。从数学上我们可以将一个时间序列 (Y_t) 分解为几个部分趋势项 (T_t)、季节项 (S_t)、周期项 (C_t) 和随机误差项 (I_t)。趋势项 (T_t) 就是我们要检验和识别的对象。它可以是确定性趋势可以用一个关于时间 (t) 的确定性函数来描述例如线性趋势 (T_t a bt)二次型趋势 (T_t a bt ct^2)或者指数趋势。这种趋势是固定的、非随机的。随机性趋势单位根过程这种趋势的表现是序列的当前值高度依赖于前一时刻的值加上一个随机冲击并且冲击的影响会永久累积下去。最典型的例子就是随机游走模型(Y_t Y_{t-1} \epsilon_t)。这种序列没有固定的趋势线但其方差会随时间无限增长表现出一种“随风飘荡”的长期记忆性。注意我们通常所说的趋势性检验主要针对的是确定性趋势。而随机性趋势本质上是非平稳性的一种极端形式带单位根需要通过平稳性检验如ADF检验来识别。2.2 平稳性统计规律的“定海神针”平稳性是时间序列分析中一个基石性的假设。一个平稳的时间序列其统计特性如均值、方差、自协方差不随时间推移而改变。这意味着序列的行为在不同时间段内是一致的我们可以用过去的信息来推断未来的规律。严格来说平稳性分为两种严平稳序列的任意有限维联合概率分布随时间平移不变。这条件非常苛刻在实际中难以验证和应用。弱平稳宽平稳这是我们实际分析中最常使用的概念。它要求均值恒定(E(Y_t) \mu) 对所有 (t) 都成立方差恒定(Var(Y_t) \sigma^2) 对所有 (t) 都成立自协方差只与时间间隔有关(Cov(Y_t, Y_{tk}) \gamma_k) 只依赖于滞后阶数 (k)与具体时间点 (t) 无关为什么平稳性如此重要因为绝大多数经典的时序模型如AR自回归、MA移动平均、ARMA自回归移动平均模型都建立在数据是弱平稳的假设之上。如果数据不平稳直接套用这些模型会导致参数估计失效、统计推断如假设检验失真最终使得预测结果变得不可靠。不平稳的数据通常表现为有明显的趋势、有季节性、或者方差随时间变化异方差。2.3 趋势与平稳的关系剪不断理还乱两者关系可以概括为存在确定性趋势必然导致序列非平稳因为均值随时间变化。但序列非平稳不一定是因为有确定性趋势还可能是随机性趋势单位根、季节性或者结构突变等。举个例子线性增长的数据(Y_t 0.5t \epsilon_t)。这个序列的均值 (E(Y_t)0.5t) 随时间增长所以它是非平稳的并且存在确定性线性趋势。随机游走数据(Y_t Y_{t-1} \epsilon_t)。这个序列的均值虽然可能恒定如果初始值为0但其方差 (Var(Y_t) t\sigma^2) 随时间无限增长所以它是非平稳的它表现出的“趋势”是随机性趋势而非确定性趋势。因此我们的分析流程通常是先检验是否存在单位根随机性趋势如果存在则通过差分使其平稳对于差分后平稳的序列再考虑是否含有确定性趋势并决定是否在模型中引入趋势项。这个顺序很重要不能乱。3. 平稳性检验详解ADF、KPSS与可视化诊断平稳性检验是我们的首要任务。这里我重点介绍两种最常用、且互为补充的检验方法ADF检验和KPSS检验。同时结合图形化观察形成综合判断。3.1 ADF检验揪出“单位根”的主力军ADF检验的全称是Augmented Dickey-Fuller检验它是Dickey-Fuller检验的增强版用于检验序列是否存在单位根即是否是非平稳的随机性趋势。核心原理它通过估计一个包含滞后项的回归方程来进行检验。方程的基本形式有三种无常数项无趋势项(\Delta Y_t \gamma Y_{t-1} \sum_{i1}^{p}\beta_i \Delta Y_{t-i} \epsilon_t)有常数项无趋势项(\Delta Y_t \alpha \gamma Y_{t-1} \sum_{i1}^{p}\beta_i \Delta Y_{t-i} \epsilon_t)有常数项有趋势项(\Delta Y_t \alpha \delta t \gamma Y_{t-1} \sum_{i1}^{p}\beta_i \Delta Y_{t-i} \epsilon_t)其中(\Delta Y_t) 是序列的一阶差分(p) 是滞后阶数用于消除误差项的自相关性。检验的假设原假设 (H_0)序列存在单位根即 (\gamma 0)序列非平稳。备择假设 (H_1)序列不存在单位根即 (\gamma 0)序列平稳。如何操作与解读在Python中我们可以使用statsmodels库的adfuller函数。关键步骤和参数选择至关重要。import pandas as pd import numpy as np from statsmodels.tsa.stattools import adfuller import matplotlib.pyplot as plt # 假设我们有一个时间序列数据 ts_data # 1. 先进行可视化观察 ts_data.plot(title原始时序数据) plt.show() # 2. 执行ADF检验 # 参数 regression 可选c仅常数, ct常数和趋势, ctt常数、线性和二次趋势, nc无 # 通常先尝试包含常数和趋势项的‘ct’如果趋势不显著再尝试‘c’。 # 参数 autolag 可选AIC, BIC, t-stat 或 None用于自动选择最佳滞后阶数p推荐‘AIC’。 result adfuller(ts_data, regressionct, autolagAIC) # 3. 解析结果 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)) # 4. 判断准则 # 如果 ADF统计量 小于 某个显著性水平如1%下的临界值或者 p-value 小于 0.05则拒绝原假设认为序列平稳。 # 反之则不能拒绝原假设认为序列非平稳。 if result[1] 0.05: print(p-value 0.05拒绝原假设序列平稳。) else: print(p-value 0.05无法拒绝原假设序列可能存在单位根非平稳。)实操心得与避坑指南滞后阶数p的选择这是影响检验结果的关键。autolagAIC是常用且相对可靠的方法它会自动选择一个使AIC信息准则最小的p值。你也可以通过观察序列的自相关图ACF图看看自相关系数在多少阶之后截尾或落入置信区间内来手动设定一个合理的p。回归方程形式的选择我个人的经验是对于有明显增长或下降形态的数据先用regressionct包含常数和趋势项。如果检验结果拒绝原假设平稳但趋势项t的系数不显著可以再用regressionc重新检验一次看看是否只是带漂移的平稳过程。如果数据围绕0值波动没有明显趋势则直接用regressionc。不要只看p值一定要结合临界值来看。有时ADF统计量非常接近临界值p值可能在0.05边缘这时下结论要谨慎。最好能结合KPSS检验和图形化观察进行综合判断。注意检验的势PowerADF检验对于接近单位根但不是单位根的过程如AR系数为0.95检验势可能不高容易犯第二类错误即实际非平稳但误判为平稳。因此单一检验结果不是金科玉律。3.2 KPSS检验换个角度检验“趋势平稳”KPSS检验Kwiatkowski-Phillips-Schmidt-Shin检验的出发点与ADF检验正好相反。它原假设是序列平稳或趋势平稳备择假设是存在单位根。核心原理KPSS检验将序列分解为确定性趋势、随机游走和平稳误差三部分。通过检验随机游走分量的方差是否为零来构建检验统计量。检验的假设原假设 (H_0)序列是水平平稳的regressionc或趋势平稳的regressionct。备择假设 (H_1)序列存在单位根非平稳。如何操作与解读同样使用statsmodels库。from statsmodels.tsa.stattools import kpss # 执行KPSS检验 # 参数 regressionc 检验水平平稳ct 检验趋势平稳。 # 参数 nlags用于计算统计量时使用的滞后阶数可选‘auto’或指定整数。 result_kpss kpss(ts_data, regressionct, nlagsauto) print(KPSS Statistic: %f % result_kpss[0]) print(p-value: %f % result_kpss[1]) print(Critical Values:) for key, value in result_kpss[3].items(): print(\t%s: %.3f % (key, value)) # 判断准则与ADF检验相反 # 如果 KPSS统计量 大于 某个显著性水平下的临界值或者 p-value 小于 0.05则拒绝原假设认为序列非平稳。 # 反之则不能拒绝原假设认为序列是趋势平稳的。 if result_kpss[1] 0.05: print(p-value 0.05拒绝原假设序列非平稳。) else: print(p-value 0.05无法拒绝原假设序列可能是趋势平稳的。)ADF与KPSS的联合使用策略 将两者结合使用可以得出更稳健的结论。通常有以下四种情况ADF检验结果 (H0: 非平稳)KPSS检验结果 (H0: 平稳)综合结论拒绝 H0 (平稳)不拒绝 H0 (平稳)序列平稳。这是最理想的情况两者结论一致。不拒绝 H0 (非平稳)拒绝 H0 (非平稳)序列非平稳。两者结论一致需要进一步处理如差分。拒绝 H0 (平稳)拒绝 H0 (非平稳)结论矛盾。可能序列是趋势平稳过程。即序列围绕一个确定性趋势波动去除趋势后是平稳的。这时应优先相信KPSS检验拒绝平稳认为序列非平稳并考虑去趋势。不拒绝 H0 (非平稳)不拒绝 H0 (平稳)结论矛盾。可能检验势不足或者序列具有长记忆性等复杂特征。需要增加样本量或结合更专业的检验如PP检验并重点依赖图形化观察。3.3 图形化观察最直观的辅助工具在运行统计检验之前和之后绘制以下图形是必不可少的步骤时序图直接观察序列是否存在明显的上升/下降趋势、季节性波动、方差是否恒定、是否存在异常点或结构突变。自相关图平稳序列的自相关系数通常会快速衰减至0附近呈指数衰减或震荡衰减。而非平稳序列的自相关系数则衰减得非常慢或者长期保持较高正值。滚动统计量图计算并绘制滚动均值、滚动标准差。如果序列平稳这两条线应该大致是水平的直线。如果滚动均值有明显趋势或滚动标准差变化很大则提示非平稳。from statsmodels.graphics.tsaplots import plot_acf, plot_pacf # 绘制自相关图 fig, axes plt.subplots(2, 1, figsize(12, 8)) plot_acf(ts_data, lags40, axaxes[0]) plot_pacf(ts_data, lags40, axaxes[1]) plt.show() # 绘制滚动统计量 rolling_mean ts_data.rolling(window12).mean() # 窗口大小根据数据频率调整 rolling_std ts_data.rolling(window12).std() plt.figure(figsize(12,6)) plt.plot(ts_data, labelOriginal, colorblue, alpha0.5) plt.plot(rolling_mean, labelRolling Mean, colorred) plt.plot(rolling_std, labelRolling Std, colorblack) plt.legend() plt.show()4. 趋势性检验详解从参数化到非参数化方法当我们通过平稳性检验特别是ADF检验确认序列非平稳且怀疑或观察到存在确定性趋势时就需要进行趋势性检验。这里的目的是判断趋势是否显著存在以及可能是什么形式的趋势。4.1 参数化方法基于模型拟合的检验参数化方法需要先假设趋势的具体函数形式如线性、二次型、指数型然后通过统计检验判断该趋势项的系数是否显著不为零。1. 线性趋势检验t检验这是最常用、最直观的方法。我们构建一个线性回归模型 [ Y_t \alpha \beta t \epsilon_t ] 其中(t) 是时间索引如1, 2, 3, ...。检验的原假设 (H_0: \beta 0)备择假设 (H_1: \beta \neq 0)。我们可以用普通最小二乘法估计模型然后对系数 (\beta) 进行t检验。如果p值小于显著性水平如0.05则拒绝原假设认为存在显著的线性趋势。import statsmodels.api as sm # 为时间序列添加时间趋势项 ts_data_df pd.DataFrame({y: ts_data}) ts_data_df[t] np.arange(1, len(ts_data_df) 1) # 创建时间索引 # 构建OLS模型添加常数项 X sm.add_constant(ts_data_df[t]) # X包含常数项和时间趋势项 model sm.OLS(ts_data_df[y], X) results model.fit() # 查看回归摘要重点关注时间趋势项‘t’的系数、t统计量和p值 print(results.summary()) # 也可以直接提取p值进行判断 p_value_trend results.pvalues[t] if p_value_trend 0.05: print(f线性趋势项的p值为{p_value_trend:.4f}小于0.05存在显著的线性趋势。) else: print(f线性趋势项的p值为{p_value_trend:.4f}无法拒绝‘无线性趋势’的原假设。)2. 高阶多项式趋势检验F检验如果时序图显示趋势可能是曲线形的可以尝试拟合多项式趋势 [ Y_t \alpha \beta_1 t \beta_2 t^2 ... \beta_k t^k \epsilon_t ] 我们可以通过F检验来比较包含趋势项的模型和不包含趋势项的模型只有常数项判断增加的趋势项是否显著改善了模型拟合。在statsmodels的回归摘要中会给出整个模型的F检验p值但更精确的是做模型比较的似然比检验或直接查看高阶项系数的t检验。实操心得警惕伪回归如果序列本身存在单位根非平稳直接对其做关于时间的回归即使趋势看起来显著也可能产生“伪回归”问题即t统计量失真。因此进行参数化趋势检验的前提最好是序列已经是趋势平稳的或者已经通过差分消除了单位根。一种常见的做法是先对原始序列做ADF检验如果非平稳则进行一阶差分对差分后的平稳序列再检验其是否含有常数项即漂移这等价于检验原序列是否存在线性趋势。趋势形式的预判图形观察很重要。线性趋势是一条直线二次趋势是一个抛物线。如果拿不准可以分别拟合线性、二次模型然后比较它们的调整后R方或AIC/BIC选择更优的模型。AIC/BIC越小越好。4.2 非参数化方法Mann-Kendall趋势检验当数据不满足正态分布假设或者存在异常值、数据是序数尺度时参数化方法可能失效。这时Mann-Kendall趋势检验这种非参数方法就显示出其优势。它不假设趋势的具体形式也不要求数据服从特定分布稳健性很强。核心原理M-K检验通过比较序列中所有可能的数据对 ((Y_i, Y_j), ij)计算其中 (Y_j Y_i) 的对数减去 (Y_j Y_i) 的对数得到一个标准化统计量 (Z)。该统计量服从标准正态分布。原假设 (H_0)序列没有单调趋势。备择假设 (H_1)序列存在单调上升或下降趋势。如何操作与解读可以使用pymannkendall这个方便的库。# 安装pip install pymannkendall import pymannkendall as mk # 执行Mann-Kendall趋势检验 result_mk mk.original_test(ts_data) print(f趋势类型: {result_mk.trend}) print(fp值: {result_mk.p}) print(f统计量S: {result_mk.s}) print(f斜率Sen‘s Slope: {result_mk.slope}) # 趋势的估计斜率非常有用 print(f截距: {result_mk.intercept}) # 判断 if result_mk.p 0.05: print(fp值小于0.05存在显著的{result_mk.trend}趋势。) print(f估计的Sen斜率为{result_mk.slope:.4f}表示平均每单位时间序列变化{result_mk.slope:.4f}。) else: print(p值大于等于0.05无法拒绝‘无单调趋势’的原假设。)M-K检验的独特优势Sen‘s Slope森斜率这是M-K检验附带的一个非常有用的估计量。它表示趋势的中位数斜率对异常值不敏感能更稳健地反映趋势的强度。例如Sen‘s Slope 0.5意味着序列值平均每个时间单位增加0.5。无需分布假设适用于各种类型的数据。对单调趋势敏感无论是线性还是非线性的单调趋势都能检测出来。注意事项M-K检验只能检测单调趋势一直上升或一直下降。对于先升后降或更复杂的非单调趋势它可能无法有效识别或者会得出“无趋势”的结论。序列存在自相关性会严重影响M-K检验的结果使其更容易拒绝原假设即更容易误判为有趋势。因此在应用前最好先检查序列的自相关性。如果存在显著自相关需要使用改进的M-K检验方法如pymannkendall库中的hamed_rao_modification_test。5. 综合实战流程与案例拆解理论说再多不如一个完整的案例来得实在。假设我们拿到某电商平台2010年至2023年的月度GMV数据我们的目标是分析其长期趋势并为后续的预测模型做准备。5.1 步骤一数据导入与初步观察import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns from statsmodels.tsa.stattools import adfuller, kpss import statsmodels.api as sm import pymannkendall as mk import warnings warnings.filterwarnings(ignore) # 1. 加载数据假设数据已处理好为时间索引的Series # df pd.read_csv(gmv_monthly.csv, parse_dates[date], index_coldate) # ts df[gmv] # 这里我们模拟生成一组带有线性增长趋势和季节性的非平稳数据 np.random.seed(42) n_periods 168 # 14年 * 12个月 t np.arange(n_periods) trend 0.8 * t # 线性趋势 seasonal 10 * np.sin(2 * np.pi * t / 12) # 年度季节性 noise np.random.normal(0, 5, n_periods) # 随机噪声 ts pd.Series(trend seasonal noise, indexpd.date_range(start2010-01, periodsn_periods, freqMS)) ts.name Simulated_GMV # 2. 绘制时序图 plt.figure(figsize(14, 6)) plt.plot(ts) plt.title(Simulated Monthly GMV Data (2010-2023)) plt.xlabel(Date) plt.ylabel(GMV) plt.grid(True) plt.show()通过时序图我们能清晰地看到数据具有强烈的上升趋势和规律的年度周期性波动。初步判断该序列极有可能是非平稳的。5.2 步骤二平稳性检验综合诊断我们同时运用ADF检验、KPSS检验和图形化工具。# 1. ADF检验 (包含常数和趋势项) print(*50) print(ADF检验结果:) adf_result adfuller(ts, regressionct, autolagAIC) print(fADF Statistic: {adf_result[0]:.4f}) print(fp-value: {adf_result[1]:.4f}) print(Critical Values:) for key, val in adf_result[4].items(): print(f\t{key}: {val:.3f}) if adf_result[1] 0.05: print(结论拒绝原假设序列平稳。) else: print(结论无法拒绝原假设序列可能存在单位根非平稳。) # 2. KPSS检验 (检验趋势平稳) print(\n *50) print(KPSS检验结果:) kpss_result kpss(ts, regressionct, nlagsauto) print(fKPSS Statistic: {kpss_result[0]:.4f}) print(fp-value: {kpss_result[1]:.4f}) print(Critical Values:) for key, val in kpss_result[3].items(): print(f\t{key}: {val:.3f}) if kpss_result[1] 0.05: print(结论拒绝原假设序列非平稳。) else: print(结论无法拒绝原假设序列可能是趋势平稳的。) # 3. 绘制自相关图 from statsmodels.graphics.tsaplots import plot_acf fig, ax plt.subplots(figsize(10,4)) plot_acf(ts, lags40, axax) plt.title(Autocorrelation Function (ACF) of Original Series) plt.show() # 4. 绘制滚动统计量 rolling_window 12 rolling_mean ts.rolling(windowrolling_window).mean() rolling_std ts.rolling(windowrolling_window).std() fig, axes plt.subplots(2, 1, figsize(14, 8)) axes[0].plot(ts, labelOriginal, alpha0.7) axes[0].plot(rolling_mean, labelf{rolling_window}-Month Rolling Mean, colorred, linewidth2) axes[0].set_title(Original Series and Rolling Mean) axes[0].legend() axes[0].grid(True) axes[1].plot(rolling_std, labelf{rolling_window}-Month Rolling Std, colordarkgreen, linewidth2) axes[1].set_title(Rolling Standard Deviation) axes[1].legend() axes[1].grid(True) plt.tight_layout() plt.show()结果分析与决策ADF检验p值很可能远大于0.05例如0.9以上无法拒绝“存在单位根”的原假设提示序列非平稳。KPSS检验p值很可能小于0.05拒绝“序列趋势平稳”的原假设同样提示序列非平稳。自相关图ACF衰减非常缓慢在很大滞后阶数下仍显著不为0这是非平稳序列的典型特征。滚动统计量滚动均值呈现明显的上升趋势滚动标准差虽有一定波动但相对稳定。综合结论模拟的GMV序列是非平稳的。其非平稳性主要来源于确定性线性趋势和季节性。由于ADF和KPSS结论一致我们不需要纠结于“趋势平稳”的复杂情况直接进入下一步差分处理。5.3 步骤三差分处理与再次检验对于同时含有趋势和季节性的序列我们通常先进行一阶季节性差分消除季节性再观察是否需要进行一阶常规差分消除趋势。# 1. 进行一阶季节性差分周期为12个月 ts_diff_seasonal ts.diff(periods12).dropna() # 2. 对季节性差分后的序列再次进行平稳性检验ADF print(*50) print(对季节性差分后序列进行ADF检验:) adf_result_diff_s adfuller(ts_diff_seasonal, regressionc, autolagAIC) # 差分后可能无趋势用‘c’ print(fADF Statistic: {adf_result_diff_s[0]:.4f}) print(fp-value: {adf_result_diff_s[1]:.4f}) if adf_result_diff_s[1] 0.05: print(结论季节性差分后序列已平稳。) else: print(结论季节性差分后序列仍非平稳需要进一步做一阶常规差分。) ts_diff_final ts_diff_seasonal.diff().dropna() print(\n对季节性差分序列再做一阶常规差分:) adf_result_final adfuller(ts_diff_final, regressionc, autolagAIC) print(fADF Statistic: {adf_result_final[0]:.4f}) print(fp-value: {adf_result_final[1]:.4f}) if adf_result_final[1] 0.05: print(结论经过‘季节性差分常规差分’后序列平稳。) final_stationary_series ts_diff_final else: print(警告多次差分后仍不平稳需检查数据或考虑其他模型如结构突变。) final_stationary_series ts_diff_final # 暂用 else: final_stationary_series ts_diff_seasonal # 3. 绘制处理后的序列 plt.figure(figsize(14,4)) plt.plot(final_stationary_series) plt.title(Stationary Series After Differencing) plt.grid(True) plt.show()在这个模拟案例中由于我们构造的数据同时包含线性趋势和强季节性很可能需要diff(12)后再diff(1)才能达到平稳。最终我们得到一个围绕0值波动的平稳序列。5.4 步骤四趋势性检验在平稳序列或原序列上现在我们对已经平稳的序列或如果我们想直接检验原序列的趋势进行趋势性检验。方法A对原序列进行Mann-Kendall检验非参数稳健print(*50) print(对原始序列进行Mann-Kendall趋势检验:) result_mk_original mk.original_test(ts) print(f趋势方向: {result_mk_original.trend}) print(fp值: {result_mk_original.p:.6f}) print(fSen‘s Slope: {result_mk_original.slope:.4f}) if result_mk_original.p 0.05: print(f存在显著的{result_mk_original.trend}趋势平均每月变化{result_mk_original.slope:.4f}单位。)这能直接告诉我们原始数据是否存在单调上升趋势及其强度。方法B对差分后平稳序列检验“漂移”对于经过差分比如一阶差分ts.diff().dropna()后平稳的序列我们可以检验其均值即漂移项是否为0。如果差分后序列的均值显著不为0则意味着原序列存在确定性线性趋势。# 假设我们只做了一阶常规差分就平稳了 ts_diff_1 ts.diff().dropna() # 检验 ts_diff_1 的均值是否为0 (使用单样本t检验) from scipy import stats t_stat, p_val stats.ttest_1samp(ts_diff_1, 0) print(f\n一阶差分序列的均值t检验: t{t_stat:.4f}, p{p_val:.4f}) if p_val 0.05: print(差分序列均值显著不为0表明原序列存在确定性线性趋势。) print(f原序列的线性趋势斜率约为: {ts_diff_1.mean():.4f}) # 差分序列的均值近似等于原序列的趋势斜率方法C在平稳序列上拟合带时间趋势的模型如果我们最终用于建模的序列是平稳的比如final_stationary_series我们可以在ARMA等模型中加入常数项如果常数项显著也暗示原序列可能存在某种趋势需结合差分次数解释。5.5 步骤五结果整合与建模指导通过以上流程我们得出关于模拟GMV数据的完整“体检报告”平稳性原始序列非平稳。需要经过一阶季节性差分和一阶常规差分才能达到平稳。趋势性Mann-Kendall检验直接确认原始序列存在显著的单调上升趋势。对一阶差分序列的均值检验也证实了确定性线性趋势的存在并估计了趋势斜率。参数化线性回归需在平稳序列或考虑协整关系下谨慎进行也能得到显著的线性趋势系数。对后续建模的指导意义模型选择由于数据同时具有趋势和季节性且经过差分后平稳最适合的模型族是季节性ARIMA即SARIMA模型。其阶数表示为SARIMA(p, d, q)(P, D, Q, s)其中d1因为我们进行了一阶常规差分。D1因为我们进行了一阶季节性差分s12。p, q, P, Q需要通过ACF/PACF图或网格搜索来确定。建模序列我们将使用final_stationary_series这个平稳序列来识别和拟合ARMA部分。预测还原使用拟合的SARIMA模型进行预测后需要将差分和季节差分的操作逆向进行才能得到原始GMV尺度上的预测值。6. 常见问题、陷阱与排查技巧实录在实际操作中你会遇到各种各样的问题。下面是我总结的一些典型坑点和解决思路。6.1 检验结果矛盾或不确定怎么办这是最常见的问题。比如ADF检验p值0.06勉强不拒绝非平稳KPSS检验p值0.04拒绝平稳。首先信任图形证据滚动均值/标准差图、ACF图比单一的p值更可靠。如果图形强烈显示有趋势或方差变化那就应该当作非平稳处理。其次考虑检验的势和样本量样本量小的时候检验功效低容易得出“无法拒绝”的模糊结论。尽可能增加数据量。采取保守策略当结果模棱两可时优先认为序列是非平稳的并进行差分。因为对平稳序列做差分称为过差分虽然会引入额外的移动平均结构但通常比用平稳模型去拟合非平稳序列欠差分带来的危害要小。过差分后的序列ACF图可能会出现明显的负相关截尾可以帮助我们识别。尝试不同的检验设定调整ADF检验的滞后阶数(maxlag)或者使用其他单位根检验如PP检验看结论是否一致。6.2 数据存在季节性如何检验趋势季节性本身就会导致序列非平稳周期性均值变化。直接对强季节性数据做趋势检验或ADF检验结果会受到严重干扰。正确做法先进行季节性差分消除季节性影响后再对差分后的序列进行趋势性检验和平稳性检验。或者使用能够同时处理趋势和季节性的模型如TBATS、Prophet进行分解直接观察趋势分量。6.3 趋势不是线性的怎么办Mann-Kendall检验只能检测单调趋势。如果趋势是二次的先升后降或更复杂分段检验如果知道结构突变点可以分段进行M-K检验或线性拟合。使用非线性拟合尝试用二次、指数、对数函数拟合并通过比较R方、AIC等指标判断哪种形式更好。同时可以检验非线性项如t²的系数是否显著。数据变换有时对数据取对数可以将指数增长趋势转化为线性趋势便于分析和检验。6.4 序列存在自相关对M-K检验有何影响如前所述正自相关会严重增大M-K检验犯第一类错误假阳性的概率。如果你的数据是月度的经济或环境数据自相关很常见。解决方案使用考虑了自相关的改进版M-K检验如预白化处理后再检验或使用pymannkendall中的hamed_rao_modification_test等函数。6.5 差分后序列均值为0但ADF检验仍说不平稳这可能意味着序列存在高阶单位根即需要多次差分。例如随机游走的一阶差分是平稳的但随机游走的一阶差分序列再差分一次可能就过差分
返回列表