本文目录导读:

我来详细介绍如何使用Python进行ARIMA时间序列分析。
安装必要的库
pip install pandas numpy matplotlib statsmodels
基础ARIMA模型实现
1 基础数据准备和建模
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller
import warnings
warnings.filterwarnings('ignore')
# 创建示例时间序列数据
np.random.seed(42)
dates = pd.date_range('2020-01-01', periods=200, freq='D')
# 生成带有趋势和季节性的数据
trend = np.linspace(100, 150, 200)
seasonal = 10 * np.sin(2 * np.pi * np.arange(200) / 30)
noise = np.random.normal(0, 2, 200)
data = trend + seasonal + noise
# 创建DataFrame
df = pd.DataFrame({'value': data}, index=dates)
print("数据预览:")
print(df.head())
2 数据平稳性检验
def check_stationarity(series):
"""检查时间序列的平稳性"""
result = adfuller(series.dropna())
print('ADF检验结果:')
print(f'ADF统计量: {result[0]:.6f}')
print(f'p值: {result[1]:.6f}')
print(f'临界值:')
for key, value in result[4].items():
print(f'\t{key}: {value:.6f}')
if result[1] <= 0.05:
print(" 序列是平稳的 (拒绝原假设)")
return True
else:
print(" 序列是非平稳的 (无法拒绝原假设)")
return False
# 检查原始序列平稳性
print("=== 原始序列平稳性检验 ===")
is_stationary = check_stationarity(df['value'])
# 如果非平稳,进行差分
if not is_stationary:
df['value_diff'] = df['value'].diff()
print("\n=== 一阶差分后序列平稳性检验 ===")
check_stationarity(df['value_diff'].dropna())
3 确定ARIMA参数(p,d,q)
def plot_acf_pacf(series, lags=40):
"""绘制ACF和PACF图"""
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))
plot_acf(series.dropna(), lags=lags, ax=ax1)
plot_pacf(series.dropna(), lags=lags, ax=ax2)
plt.tight_layout()
plt.show()
# 绘制差分后的ACF和PACF图
print("绘制ACF和PACF图...")
plot_acf_pacf(df['value_diff'].dropna())
# 根据ACF和PACF图选择参数
# ACF: 确定MA(q) - 看截尾
# PACF: 确定AR(p) - 看截尾
# 一般先尝试简单参数: p=1, d=1, q=1
4 自动选择最优参数
from statsmodels.tsa.arima.model import ARIMA
from itertools import product
def find_best_arima_params(series, p_range=range(0, 4), d_range=range(0, 2), q_range=range(0, 4)):
"""自动搜索最优ARIMA参数"""
best_aic = float('inf')
best_order = None
results = []
for p, d, q in product(p_range, d_range, q_range):
try:
model = ARIMA(series.dropna(), order=(p, d, q))
result = model.fit()
aic = result.aic
results.append({
'order': (p, d, q),
'aic': aic
})
if aic < best_aic:
best_aic = aic
best_order = (p, d, q)
except:
continue
return best_order, best_aic, results
# 寻找最优参数
print("开始搜索最优ARIMA参数...")
best_order, best_aic, all_results = find_best_arima_params(df['value'])
print(f"最优参数: p={best_order[0]}, d={best_order[1]}, q={best_order[2]}")
print(f"最优AIC: {best_aic:.4f}")
# 显示前5个最优参数组合
all_results_sorted = sorted(all_results, key=lambda x: x['aic'])[:5]
print("\n前5个最优参数组合:")
for result in all_results_sorted:
print(f" ARIMA{result['order']}: AIC={result['aic']:.4f}")
5 训练ARIMA模型
# 使用最优参数训练模型
model = ARIMA(df['value'], order=best_order)
model_fit = model.fit()
print("\n=== 模型摘要 ===")
print(model_fit.summary())
6 模型诊断
from statsmodels.graphics.tsaplots import plot_acf
import seaborn as sns
def diagnose_model(model_fit):
"""模型诊断"""
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
# 残差图
residuals = model_fit.resid
axes[0, 0].plot(residuals)
axes[0, 0].set_title('残差图')
axes[0, 0].axhline(y=0, color='r', linestyle='--')
# 残差直方图
axes[0, 1].hist(residuals, bins=30, alpha=0.7, edgecolor='black')
axes[0, 1].set_title('残差分布')
# QQ图
from scipy import stats
stats.probplot(residuals, dist="norm", plot=axes[1, 0])
axes[1, 0].set_title('Q-Q图')
# 残差ACF
plot_acf(residuals.dropna(), lags=40, ax=axes[1, 1])
axes[1, 1].set_title('残差ACF')
plt.tight_layout()
plt.show()
# 正态性检验
stat, p_value = stats.normaltest(residuals.dropna())
print(f"正态性检验: 统计量={stat:.4f}, p值={p_value:.4f}")
# Durbin-Watson检验
from statsmodels.stats.stattools import durbin_watson
dw = durbin_watson(residuals.dropna())
print(f"Durbin-Watson统计量: {dw:.4f} (接近2表示无自相关)")
diagnose_model(model_fit)
7 预测与可视化
def forecast_and_plot(model_fit, df, steps=30):
"""预测并可视化"""
# 进行预测
forecast = model_fit.forecast(steps=steps)
forecast_index = pd.date_range(df.index[-1], periods=steps+1, freq='D')[1:]
# 获取置信区间
forecast_result = model_fit.get_forecast(steps=steps)
conf_int = forecast_result.conf_int()
# 可视化
plt.figure(figsize=(15, 6))
# 历史数据
plt.plot(df.index, df['value'], label='历史数据', color='blue')
# 预测数据
plt.plot(forecast_index, forecast, label='预测值', color='red', linewidth=2)
# 置信区间
plt.fill_between(
forecast_index,
conf_int.iloc[:, 0],
conf_int.iloc[:, 1],
color='red',
alpha=0.2,
label='95% 置信区间'
)
plt.title(f'ARIMA{best_order} 时间序列预测', fontsize=14)
plt.xlabel('日期')
plt.ylabel('值')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
return forecast, conf_int
# 进行预测
forecast_values, confidence_intervals = forecast_and_plot(model_fit, df, steps=30)
# 打印预测结果
print("\n=== 预测结果 ===")
forecast_df = pd.DataFrame({
'日期': forecast_index,
'预测值': forecast_values,
'下限(95%)': confidence_intervals.iloc[:, 0],
'上限(95%)': confidence_intervals.iloc[:, 1]
})
print(forecast_df.head(10))
实际应用示例:销售预测
# 生成模拟销售数据
np.random.seed(123)
dates_sales = pd.date_range('2023-01-01', periods=365, freq='D')
# 添加趋势、季节性和随机波动
base = 1000
weekly_pattern = 100 * np.sin(2 * np.pi * np.arange(365) / 7)
monthly_pattern = 200 * np.sin(2 * np.pi * np.arange(365) / 30)
growth = np.linspace(0, 300, 365)
noise = np.random.normal(0, 50, 365)
sales = base + weekly_pattern + monthly_pattern + growth + noise
sales = np.maximum(sales, 0) # 确保非负
df_sales = pd.DataFrame({'sales': sales}, index=dates_sales)
print("=== 销售数据ARIMA分析 ===")
# 1. 数据可视化
plt.figure(figsize=(15, 5))
plt.plot(df_sales.index, df_sales['sales'], label='日销售额', alpha=0.7)'每日销售数据')
plt.xlabel('日期')
plt.ylabel('销售额')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 2. 确定差分阶数
d_value = 1 # 通常销售额数据需要一阶差分
# 3. 搜索最优p和q
best_order, _, _ = find_best_arima_params(
df_sales['sales'],
p_range=range(0, 5),
d_range=[1],
q_range=range(0, 5)
)
print(f"最优ARIMA参数: {best_order}")
# 4. 训练模型
model_sales = ARIMA(df_sales['sales'], order=best_order)
model_sales_fitted = model_sales.fit()
# 5. 预测未来30天
forecast_sales = model_sales_fitted.forecast(steps=30)
forecast_index = pd.date_range(df_sales.index[-1], periods=31, freq='D')[1:]
# 6. 可视化结果
plt.figure(figsize=(15, 6))
plt.plot(df_sales.index[-90:], df_sales['sales'][-90:], label='历史数据(最近90天)', color='blue')
plt.plot(forecast_index, forecast_sales, label='30天预测', color='red', linewidth=2)f'销售额预测 (ARIMA{best_order})', fontsize=14)
plt.xlabel('日期')
plt.ylabel('销售额')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
# 7. 预测性能评估
from sklearn.metrics import mean_absolute_error, mean_squared_error
# 使用最后30天作为测试集
test_size = 30
train_data = df_sales['sales'][:-test_size]
test_data = df_sales['sales'][-test_size:]
model_temp = ARIMA(train_data, order=best_order)
model_temp_fit = model_temp.fit()
predictions = model_temp_fit.forecast(steps=test_size)
mae = mean_absolute_error(test_data, predictions)
rmse = np.sqrt(mean_squared_error(test_data, predictions))
print(f"\n=== 模型评估 ===")
print(f"MAE (平均绝对误差): {mae:.2f}")
print(f"RMSE (均方根误差): {rmse:.2f}")
print(f"MAPE (平均绝对百分比误差): {(mae/test_data.mean()*100):.2f}%")
高级技巧和注意事项
1 季节性ARIMA (SARIMA)
from statsmodels.tsa.statespace.sarimax import SARIMAX
# SARIMA模型(带季节性)
seasonal_order = (1, 1, 1, 7) # P, D, Q, S (S=7表示周季节性)
sarima_model = SARIMAX(
df_sales['sales'],
order=(best_order[0], best_order[1], best_order[2]),
seasonal_order=seasonal_order,
enforce_stationarity=False,
enforce_invertibility=False
)
sarima_result = sarima_model.fit()
print("SARIMA模型摘要:")
print(sarima_result.summary())
2 异常值处理
def detect_and_handle_outliers(series, threshold=3):
"""检测并处理异常值"""
mean = series.mean()
std = series.std()
# 检测异常值
outliers = np.abs(series - mean) > threshold * std
print(f"检测到 {outliers.sum()} 个异常值")
# 用中位数替换异常值
series_clean = series.copy()
median_val = series.median()
series_clean[outliers] = median_val
return series_clean, outliers
# 处理异常值
clean_data, outliers = detect_and_handle_outliers(df_sales['sales'])
df_sales['sales_clean'] = clean_data
3 模型比较
def compare_models(series, orders_list):
"""比较多个ARIMA模型"""
results = []
for order in orders_list:
try:
model = ARIMA(series.dropna(), order=order)
result = model.fit()
results.append({
'order': order,
'aic': result.aic,
'bic': result.bic,
'hqic': result.hqic
})
except:
print(f"ARIMA{order} 模型无法拟合")
results_df = pd.DataFrame(results)
return results_df.sort_values('aic')
# 比较不同模型
orders_to_compare = [(1,1,1), (2,1,2), (1,1,2), (2,1,1), (3,1,2)]
comparison_results = compare_models(df_sales['sales'], orders_to_compare)
print("\n模型比较结果:")
print(comparison_results)
4 滚动预测
def rolling_forecast(series, order, window_size=30):
"""滚动预测"""
predictions = []
actual_values = []
for i in range(window_size, len(series) - window_size):
train = series[:i]
test = series[i:i+window_size]
# 训练模型并预测
model = ARIMA(train, order=order)
fitted = model.fit()
forecast = fitted.forecast(steps=window_size)
predictions.extend(forecast)
actual_values.extend(test)
return np.array(predictions), np.array(actual_values)
# 执行滚动预测
window = 30
preds, actuals = rolling_forecast(
df_sales['sales'][:200],
best_order,
window_size=window
)
# 计算性能指标
mae_rolling = mean_absolute_error(actuals, preds)
rmse_rolling = np.sqrt(mean_squared_error(actuals, preds))
print(f"\n滚动预测评估:")
print(f"样本数: {len(preds)}")
print(f"MAE: {mae_rolling:.2f}")
print(f"RMSE: {rmse_rolling:.2f}")
完整的使用流程总结
- 数据准备: 确保数据是时间序列格式(pandas DatetimeIndex)
- 平稳性检验: 使用ADF检验,必要时进行差分
- 参数确定:
- 使用ACF/PACF图
- 或自动搜索最优参数
- 模型训练: 使用ARIMA或SARIMAX类
- 模型诊断: 检查残差是否满足白噪声假设
- 预测: 使用forecast()方法进行预测
- 评估: 使用MAE、RMSE等指标评估模型性能
这样你就可以用Python进行完整的ARIMA时间序列分析了!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播