Augmented Dickey-Fuller检验出现NaN值的原因及解决方法
ADF检验出现NaN结果的原因与解决办法
问题背景
我正在进行时间序列预测,通过Augmented Dickey-Fuller(ADF)检验的p值验证序列平稳性,使用的代码如下:
from statsmodels.tsa.stattools import adfuller df = pd.read_csv(path) adfuller(df['values'])
正常情况下,检验会输出包含ADF统计量、p值、滞后数和观测数的结果:
ADF: -12.792326588071095 P-Value: 7.033712977770105e-24 Number of Lags: 0 Number of observations: 165
但部分时间序列的检验结果中,ADF值和P-Value均为NaN:
ADF: nan P-Value: nan Number of Lags: 0 Number of observations: 165
我需要明确三个问题:该结果代表什么?出现的原因是什么?如何解决此问题?
附相关DataFrame样例:
df.head()
| value | |
|---|---|
| 0 | 35.54 |
| 1 | 2.022 |
| 2 | 1.94 |
| 3 | 0.0 |
| 4 | 34.89 |
df.head().to_csv() # 输出:',value\r\n0,35.54\r\n1,2.022\r\n2,1.94\r\n3,0.0\r\n4,34.89\r\n'
一、NaN结果的含义
ADF统计量和p值为NaN,说明检验无法完成有效计算,无法对序列的平稳性给出结论,计算过程中出现了数值异常或逻辑中断。
二、出现NaN的常见原因
- 数据存在缺失值/无穷大值:如果目标列包含
NaN、inf或-inf,ADF检验的核心计算会中断,直接返回NaN。 - 序列方差为0(或极小):若整个序列的取值完全一致(比如全为0),或者方差小到触发数值计算不稳定,ADF统计量无法正常推导,会输出NaN。
- 列名/数据类型不匹配:代码中使用
df['values'],但样例数据的列名是value,如果实际数据列名不匹配,可能拿到空序列;另外如果数据类型是非数值型(比如字符串),也会导致计算失败。 - statsmodels版本缺陷:旧版本的statsmodels在处理某些特殊序列(如极端值、短序列)时,可能存在计算bug,导致返回NaN。
三、解决办法
针对上述原因,对应解决方案如下:
1. 清理数据中的异常值
先检查并处理目标列的缺失值和无穷大值:
import numpy as np import pandas as pd # 检查缺失值数量 print(df['values'].isna().sum()) # 检查无穷大值数量 print(df['values'].isin([np.inf, -np.inf]).sum()) # 处理缺失值:向前填充(可根据业务选择其他方式,比如均值填充) df['values'] = df['values'].fillna(method='ffill') # 替换无穷大值为序列中位数 df['values'] = df['values'].replace([np.inf, -np.inf], df['values'].median()) # 检查序列方差,若方差接近0,考虑差分处理 print(df['values'].var()) if df['values'].var() < 1e-6: df['values'] = df['values'].diff().dropna()
2. 修正列名与数据类型
- 确认代码中的列名与实际数据一致,比如样例列名为
value,则代码应改为adfuller(df['value'])。 - 确保数据为数值型:
df['values'] = pd.to_numeric(df['values'], errors='coerce')
3. 升级statsmodels版本
运行以下命令更新到最新稳定版,修复旧版本的bug:
pip install --upgrade statsmodels
4. 手动指定滞后项参数
默认情况下adfuller会自动选择滞后数,若自动选择逻辑出问题,可手动指定最大滞后项:
adfuller(df['values'], maxlag=5) # 根据序列长度调整maxlag值
5. 尝试替代检验方法
如果ADF检验始终无法正常计算,可以使用KPSS检验作为替代,同样用于验证平稳性:
from statsmodels.tsa.stattools import kpss kpss_result = kpss(df['values']) print(f'KPSS统计量: {kpss_result[0]}') print(f'p-value: {kpss_result[1]}')
内容的提问来源于stack exchange,提问作者Ajipani
相关产品推荐
相关产品推荐

