python学习打卡day57
DAY 57 经典时序模型1
知识点回顾
- 序列数据的处理:
- 处理非平稳性:n阶差分
- 处理季节性:季节性差分
- 自回归性无需处理
- 模型的选择
- AR(p) 自回归模型:当前值受到过去p个值的影响
- MA(q) 移动平均模型:当前值收到短期冲击的影响,且冲击影响随时间衰减
- ARMA(p,q) 自回归滑动平均模型:同时存在自回归和冲击影响
作业:检索下经典的时序单变量数据集有哪些,选择一个尝试观察其性质。
数据集选择的是经典的国际航空公司乘客数据集
数据集地址:国际航空公司乘客 --- International airline passengers
1.原数组展示
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
from statsmodels.tsa.stattools import adfuller
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.tsa.statespace.sarimax import SARIMAX
# 读取数据
data = pd.read_csv('international-airline-passengers.csv')# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False# 设置图片清晰度
plt.rcParams['figure.dpi'] = 300def parse_date(s):month_part, year_part = s.split('-')# 判断年份简写,这里假设49代表1949,60代表1960等(根据数据集实际情况,若有20xx 可再细化逻辑)if int(year_part) <= 99: year = 1900 + int(year_part)else:year = int(year_part)return f'{year}-{month_part}'# 转换日期列
data['Month'] = pd.to_datetime(data['Month'].apply(parse_date))# 创建图表
plt.figure(figsize=(12, 6))
plt.plot(data['Month'], data['passengers'], marker='o', linestyle='-', color='#00A1FF')# 添加标题和轴标签
plt.title('国际航空乘客数量趋势图', fontsize=14, fontweight='bold')
plt.xlabel('日期', fontsize=12)
plt.ylabel('乘客数量(千)', fontsize=12)# 设置X轴为日期格式,并自定义刻度间隔(每6个月显示一次标签)
ax = plt.gca()
ax.xaxis.set_major_locator(mdates.MonthLocator(interval=6)) # 每6个月一个刻度
ax.xaxis.set_major_formatter(mdates.DateFormatter('%b-%y')) # 格式化为"月-年"# 旋转x轴标签并右对齐,提升可读性
plt.xticks(rotation=45, ha='right')# 移除左、右、上三边的边框,使图表更简洁
plt.gca().spines['left'].set_visible(False)
plt.gca().spines['right'].set_visible(False)
plt.gca().spines['top'].set_visible(False)# 添加网格横线,增强数据可读性
plt.grid(axis='y', linestyle='--', alpha=0.7)# 调整布局,防止标签被截断
plt.tight_layout()# 显示图形
plt.show()
有着显著的季节性和趋势
ADF检验一下
# ADF检验
adf_result_original = adfuller(data['passengers'].values)
print(f'原始数据的ADF检验结果:')
print(f' ADF Statistic: {adf_result_original[0]}')
print(f' p-value: {adf_result_original[1]}') # p-value会非常大,说明是非平稳的
原始数据的ADF检验结果:
ADF Statistic: 0.8153688792060463
p-value: 0.991880243437641
P值这么高,显然数据不稳定
2.季节性差分
# ======================== 季节性差分(周期 S=12) ========================
data.set_index('Month', inplace=True)
# 对原始数据做季节性差分(周期12,即一年的季节周期)
data_seasonal_diff = data['passengers'].diff(periods=12).dropna() # 可视化季节性差分结果
plt.figure(figsize=(12, 4))
plt.plot(data_seasonal_diff, color='#4CAF50', label='季节性差分(S=12)')
plt.title('季节性差分后的数据(周期 S=12)', fontsize=14)
plt.xlabel('日期', fontsize=12)
plt.ylabel('乘客数量差分', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()# ======================== ADF 检验(验证平稳性) ========================
adf_result_seasonal = adfuller(data_seasonal_diff)
print(f'季节性差分后数据的 ADF 检验结果:')
print(f' ADF Statistic: {adf_result_seasonal[0]}')
print(f' p-value: {adf_result_seasonal[1]}')
季节性差分后数据的 ADF 检验结果:
ADF Statistic: -3.383020726492481
p-value: 0.011551493085514954
3.再对季节性差分结果做一阶差分(处理趋势)
# ======================== 2. 一阶差分(在季节性差分基础上) ========================
# 再对季节性差分结果做一阶差分(处理趋势性)
data_seasonal_first_diff = data_seasonal_diff.diff().dropna()# 可视化最终差分结果
plt.figure(figsize=(12, 4))
plt.plot(data_seasonal_first_diff, color='#FF5722', label='季节性差分 + 一阶差分')
plt.title('先季节性差分(S=12)、再一阶差分后的数据', fontsize=14)
plt.xlabel('日期', fontsize=12)
plt.ylabel('最终差分结果', fontsize=12)
plt.xticks(rotation=45, ha='right')
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.legend()
plt.tight_layout()
plt.show()
ADF检验
# ======================== 3. ADF 检验(验证最终差分后的数据是否平稳) ========================
adf_result = adfuller(data_seasonal_first_diff)
print(f'最终差分后数据的 ADF 检验结果:')
print(f' ADF Statistic: {adf_result[0]}')
print(f' p-value: {adf_result[1]}')
print(f' Critical Values:')
for key, value in adf_result[4].items():print(f' {key}: {value:.2f}')
最终差分后数据的 ADF 检验结果:
ADF Statistic: -15.595618083746338
p-value: 1.856511600123444e-28
Critical Values: 1%: -3.48 5%: -2.88 10%: -2.58
4.绘制ACF、PACF图查看数据适合什么模型
plt.figure(figsize=(12, 8))# 3.1 绘制差分后数据的时间序列图
plt.subplot(311)
plt.plot(data_seasonal_first_diff)
plt.title('差分后国际航空乘客数量')
plt.xlabel('日期')
plt.ylabel('乘客数量差分')# 3.2 绘制自相关函数(ACF)图
plt.subplot(312)
plot_acf(data_seasonal_first_diff, lags=40, ax=plt.gca())
plt.title('自相关函数(ACF)')# 3.3 绘制偏自相关函数(PACF)图
plt.subplot(313)
plot_pacf(data_seasonal_first_diff, lags=40, ax=plt.gca())
plt.title('偏自相关函数(PACF)')plt.tight_layout()
plt.show()
根据AI分析选择AR模型
从图中可以观察到:
- PACF(偏自相关函数):在滞后 1 阶后快速截断(值落入置信区间,趋近于 0),但后续滞后阶数(如滞后 2 阶、3 阶等)仍有小幅度波动(不过整体趋势是快速衰减 )。
- ACF(自相关函数):呈现拖尾特征(缓慢衰减,没有明显的截断点 )。
模型推荐
根据上述特征:
- PACF 呈现 “1 阶左右截断 + 拖尾”,但更接近 AR 模型 的特征(PACF 截断,ACF 拖尾 )。
- 由于 PACF 并非 “严格在 1 阶后完全截断”(可能受数据噪声或季节性影响 ),但整体趋势符合 AR 模型 的判断逻辑。
5 .AR模型
# 1.3 根据ACF/PACF图的诊断,建立ARIMA(1,0,0)模型
model_ar = ARIMA(data_seasonal_first_diff, order=(1, 0, 0)).fit()
print("\nAR(2)模型诊断报告:")
print(model_ar.summary())
效果也就一般般
@浙大疏锦行