You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

时间序列平稳性检验:R与Python结果不一致问题排查及正确流程

R与Python中ADF检验结果相反的原因及正确流程

嗨,我来帮你拆解这个问题——R和Python的ADF检验结果相反,大概率是默认参数差异导致的,先看你提供的R代码可能存在的问题,再讲正确的检验流程。

一、你的R代码可能的潜在问题

你给出的代码片段是:

rd <- read.table('Data/TS.csv', sep = ',', header = TRUE)

这里有几个需要确认的点:

  • 数据类型是否正确read.table读取的是data.frame,你后续调用adf.test(rd$某列)时,要确保该列是数值型向量,如果csv里有格式问题(比如日期字符串混在数值列、缺失值用非标准符号),可能导致数据读取错误,影响检验结果。
  • 是否踩了默认参数的坑tseries::adf.test()的默认行为和Python的adfuller()完全不同,这是结果相反的核心原因——我后面会详细说明。
  • 有没有规范时间序列结构:如果你的数据是规则时间序列(比如月度、年度),建议转换为ts对象(ts_data <- ts(rd$列名, start = c(2020,1), frequency = 12)),虽然adf.test能处理向量,但规范的时间序列对象能避免隐性问题。

二、为什么R和Python的ADF结果会相反?核心是默认模型不同!

这是最常见的原因,两个函数的默认ADF模型形式完全不一样:

  • R的tseries::adf.test():默认拟合包含常数项 + 线性趋势项的ADF模型,备择假设是“趋势平稳”(即数据有确定趋势,但去除趋势后是平稳的)。
  • Python的statsmodels.tsa.stattools.adfuller():默认只拟合常数项的ADF模型,不包含趋势项,备择假设是“平稳(无趋势)”。

举个例子:如果你的数据是趋势平稳的(比如有逐年上升的确定趋势,但残差是平稳的),那么:

  • R的adf.test()会拒绝“存在单位根”的原假设,认为数据是趋势平稳的(p<0.05);
  • Python的默认adfuller()因为没加入趋势项,会把趋势误判为单位根的表现,接受原假设(p>0.05),认为数据非平稳。

这完全符合你遇到的情况!

三、R和Python中检验时间序列平稳性的正确流程

第一步:数据预处理

不管用哪种语言,先把数据搞对:

  • 检查数据类型:确保是数值型,无异常值、缺失值(缺失值可以删除或插值处理);
  • 规范时间序列结构:R中用ts对象,Python中用pandas的Series并设置正确的时间索引。

第二步:可视化初步判断

先通过图表直观感受:

  • 绘制时间序列图:看是否有明显趋势、季节性;
  • 绘制ACF/PACF图:如果ACF缓慢衰减,大概率非平稳;如果快速衰减,可能平稳。

第三步:ADF检验的正确姿势(统一参数,避免默认坑)

要让两个语言的结果一致,必须统一模型形式滞后阶数

在R中:

如果你想和Python默认行为对齐(仅常数项模型),不要用tseries::adf.test(),改用更灵活的urca::ur.df()

library(urca)
# type="drift"对应Python的regression='c'(仅常数项)
# selectlags="AIC"用AIC选择最优滞后阶数,和Python默认一致
df_test <- ur.df(rd$你的列名, type = "drift", selectlags = "AIC")
# 查看检验结果,重点看p值(在"Test Statistic"对应的p-value)
summary(df_test)

如果想和R的adf.test()默认对齐(常数+趋势项),用:

df_test <- ur.df(rd$你的列名, type = "trend", selectlags = "AIC")
summary(df_test)

在Python中:

如果你想和R的adf.test()默认对齐(常数+趋势项),指定regression='ct'

from statsmodels.tsa.stattools import adfuller
# regression='ct'对应R的adf.test默认模型
result = adfuller(你的数据, regression='ct')
print(f"ADF统计量: {result[0]}")
print(f"p值: {result[1]}")

如果想保持Python默认(仅常数项),但要和R指定滞后阶数对齐(R默认是trunc((n-1)^(1/3))):

n = len(你的数据)
maxlag = int((n-1)**(1/3))
result = adfuller(你的数据, maxlag=maxlag, autolag=None)

第四步:结合其他检验方法

ADF检验不是唯一的,建议结合KPSS检验(原假设是平稳)交叉验证:

  • R中用tseries::kpss.test()
  • Python中用statsmodels.tsa.stattools.kpss()

如果ADF拒绝原假设(平稳)且KPSS接受原假设(平稳),才能更确定数据是平稳的。

内容的提问来源于stack exchange,提问作者Leo

火山引擎 最新活动