基于SARIMA模型的新能源汽车产销量分析

        这是一个简单的小案例,利用季节性移动平均模型(SARIMA)对2024年新能源汽车的产销量进行分析,大家可以简单了解一下如何使用这个模型对有周期性的时序数据进行预测分析,本篇博客用于学习记录。

        SARIMA模型ARIMA模型的扩展,用于处理具有明显季节性变化的时间序列数据。它在ARIMA模型的基础上添加了季节性成分,以更好地捕捉季节性变化的影响。当然季节性不仅局限于一年四季这种自然季节的周期性变化,任何类型的周期性都可以。比如说季节性可以是一天内的小时变化(24)、一周内的星期变化(7)、一个月内的日变化(30)、一年内的月变化(12)。

        本例就是利用2015年-2023年的新能源汽车月产销量来预测2024年的月产销量,一个周期便是12个月。

         SARIMA模型介绍可以看看这个博主写的,很详细:季节性时间序列预测之SARIMA模型

下面开始我们的小案例吧!!!

先导入咱们需要用的库,我的代码是在jupyter notebook运行的。

import pandas as pd
import numpy as np
# 基本的数据处理包

import matplotlib.pyplot as plt 
import seaborn as sns
# 这两段是为了绘制小提琴图

from tqdm import tqdm  # 导入 tqdm 库,给网格搜索的时候加进度条

from pyecharts.globals import CurrentConfig, NotebookType
CurrentConfig.NOTEBOOK_TYPE = NotebookType.JUPYTER_LAB
# 加上面这两段代码是为了让jupyter notebook能显示所作的图像


import pyecharts.options as opts
from pyecharts.charts import Line, Radar, Scatter
from pyecharts.globals import ThemeType
# 本实验最重要的绘图工具

import itertools
from statsmodels.tsa.statespace.sarimax import SARIMAX
from sklearn.metrics import mean_squared_error
# 调用SARIMA模型需要的包

 1. 数据读入

# 按月读取2015年1月1日-2024年3月1日的数据
df1 = pd.read_excel("2014-2024年新能源汽车产销量(月).xlsx", sheet_name = 0)
def date(para):
    if type(para) == int:
        delta = pd.Timedelta(str(int(para))+'days')
        time = pd.to_datetime('1899-12-30') + delta
        return time
    else:
        return para

df1['时间'] = df1['时间'].apply(date)
df1.set_index('时间', inplace=True)
df1.index = pd.DatetimeIndex(df1.index).to_period('M')# 设置周期频率

2. 检测空缺值

                绘制产销量曲线——这里推荐大家作图可以试试pyecharts好用图也好看!!!

        通过绘制图像可以看到在2015-2017年之间存在明显的断点,并且数据与时间有相关性,初步考虑利用季节性移动平均模型(SARIMA)填补空缺值,并利用该模型对2024年的新能源汽车的产销量进行预测分析;

代码实现:

# 将周期对象转换为字符串形式
x_axis_data = [str(period) for period in df1.index.tolist()]

yields = (
    Line(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    .add_xaxis(x_axis_data)
    .add_yaxis(series_name="月产量", 
               is_smooth=True,
               y_axis=df1['产量(万辆)'].tolist(), 
               symbol_size=10, 
               # linestyle_opts=opts.LineStyleOpts(color="blue"),
               label_opts=opts.LabelOpts(is_show=False))
    .add_yaxis(series_name="月销量", 
           is_smooth=True,
           y_axis=df1['销量(万辆)'].tolist(), 
           symbol_size=10, 
           # linestyle_opts=opts.LineStyleOpts(color="blue"),
           label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(title_opts=opts.TitleOpts(title="2015年-2024年3月新能源汽车的月产销量"),
                     xaxis_opts=opts.AxisOpts(type_='category', name="时间"),
                     yaxis_opts=opts.AxisOpts(type_='value', name="产销量/万辆"),
                     )
)
yields.load_javascript()
yields.render_notebook()

3. 检测异常值

                绘制小提琴图——这里推荐使用小提琴图,因为小提琴图相较于箱线图更加好看,而且在数模比赛中也很受青睐!!!

        根据小提琴图可以看到,产销量的取值集中分布在[0,25]这个区间内,并且两个小提琴图十分相似,峰值几乎相等,和我国新能源汽车的发展趋势相符,不考虑进行异常值剔除。

代码实现:

custom_palette = ["#ff7f0e", "#2ca02c"]

# 绘制小提琴图,并指定调色板
sns.violinplot(data=df1, inner="quartile", palette=custom_palette)
plt.title('产销量小提琴图')
plt.xlabel('Groups')
plt.ylabel('Values')
plt.show()

4. 检测每年月销量的平稳性

        我国于2014年发行了新能源汽车的相关政策,根据上图可以看到,在2020年以前,新能源汽车的月产量均在25万辆以下,并且发展趋势也相对平缓。2020年以后,受疫情的影响,产量会有所波动,但总体成上升趋势,从2021年开始有了明显的提升,在2022-2024年得到了迅速的发展!

代码实现:

# 导入数据
sales_data = [df1['产量(万辆)'].tolist()[i*12: (i+1)*12] for i in range(10)]

# 提取年份
years = [str(i) for i in range(2015, 2025)]

# 初始化 Line 对象
line = Line()

# 添加折线数据
for year, sales in zip(years, sales_data):
    line.add_xaxis(range(1, 13))
    line.add_yaxis(f"{year}", sales)

# 设置全局参数
line.set_global_opts(
    title_opts=opts.TitleOpts(title="月产量"),
    xaxis_opts=opts.AxisOpts(type_="category", name="月份"),
    yaxis_opts=opts.AxisOpts(name="产量(万辆)"),
    tooltip_opts=opts.TooltipOpts(trigger="axis", axis_pointer_type="cross"),
    legend_opts=opts.LegendOpts(pos_left="center", orient="horizontal")
)
line.load_javascript()
line.render_notebook()

5. SARIMA建模

        根据获取到的2015-2024年新能源汽车月销售数据,建立SARIMA模型,同时为了避免空缺值对模型造成的影响,考虑利用完整年份的数据进行建模;

建模步骤如下:

  1. 获取2015-2024年新能源汽车产销量数据,对时间列索引转化为以月份为单位的周期索引;
  2. 初步限定SARIMA模型参数p、d、q的参数范围,利用网格搜索法计算每组参数的均方根误差,并实时选取误差最小的参数组;
  3. 选取最优参数进行模型拟合,设置SARIMA模型的周期为12,带入原始日期进行拟合并可视化;
  4. 设置预测日期为2024年1月到2024年12月,利用训练好的模型进行预测,可视化预测结果。

        首先是对新能源汽车产量的拟合。在第一步利用to_period()函数将获取的数据日期索引更改为按月为单位的周期索引,设置p的参数范围为(0,5), d的参数范围为(0,3), q的参数范围为(0,5),通过for循环对计算每组参数值的RMSE,最终得到SARIMA模型的最优参数为(2,1,4)

代码实现:

train = df1[:108] # 选取完整的时序数据

# 定义参数范围
p_range = range(0, 5)  # 自回归阶数范围
d_range = range(0, 3)  # 差分阶数范围
q_range = range(0, 5)  # 移动平均阶数范围
parameters = itertools.product(p_range, d_range, q_range)

best_score = float('inf')
best_params = None

# 网格搜索
for param in tqdm(parameters, total=len(p_range)*len(d_range)*len(q_range)):
    try:
        # 使用当前参数拟合 SARIMA 模型
        model = SARIMAX(train['产量(万辆)'], order=param, seasonal_order=(1, 1, 1, 12))
        result = model.fit()
        
        # 计算模型的均方根误差(RMSE)
        predicted_sales = result.predict(start=train.index[0], end=train.index[-1])
        rmse = np.sqrt(mean_squared_error(train['产量(万辆)'], predicted_sales))
        
        # 打印RMSE
        print("RMSE:", rmse)
        
        # 更新最优参数
        if rmse < best_score:
            best_score = rmse
            best_params = param
    except:
        continue

print("Best Parameters:", best_params)

# 将 PeriodIndex 转换为 Timestamp 格式
predicted_index = df3.index.to_timestamp()

# 使用 SARIMA 模型进行产量拟合和预测
model = SARIMAX(train['产量(万辆)'], order=(2, 1, 4), seasonal_order=(1, 1, 1, 12))
result = model.fit()

# 预测
predicted_yields = result.predict(start=predicted_index[0], end=predicted_index[-1])

predicted_yields

         调用statsmodels库中的SARIMA模型,设置周期为12个月,然后进行模型的训练,拟合结果如下:

代码实现:

# 将周期对象转换为字符串形式
x_axis_data = [str(period) for period in df1.index.tolist()]

predict = (
    Line(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    .add_xaxis(x_axis_data)
    .add_yaxis(series_name="月产量", 
               is_smooth=True,
               y_axis=df3['产量(万辆)'].tolist(), 
               symbol_size=10, 
               # linestyle_opts=opts.LineStyleOpts(color="pink"),
               label_opts=opts.LabelOpts(is_show=False))
    .add_yaxis(series_name="预测产量", 
           is_smooth=True,
           y_axis=predicted_sales.tolist(), 
           symbol_size=10, 
           linestyle_opts=opts.LineStyleOpts(color="red"),
           label_opts=opts.LabelOpts(is_show=False))
    .set_global_opts(title_opts=opts.TitleOpts(title="2015年-2024年3月新能源汽车的月产销量"),
                     xaxis_opts=opts.AxisOpts(type_='category', name="时间"),
                     yaxis_opts=opts.AxisOpts(type_='value', name="产量/万辆"),
                     )
)
predict.load_javascript()
predict.render_notebook()

        可以看到,预测曲线基本拟合了原始图像,下面设定预测区间为2024年1月到2024年12月,2024年每月新能源汽车产量效果图如下:

代码实现:

# 预测未来2024年的产量变化
predicted_2024 = result.predict(start='2024-01', end='2024-12', freq='M')
predicted_2024 = [round(i, 2) for i in predicted_2024]
# 将周期对象转换为字符串形式
x_axis_data = [f'2024-{i}' for i in range(1, 13)]

predict_2024 = (
    Line(init_opts=opts.InitOpts(theme=ThemeType.LIGHT))
    .add_xaxis(x_axis_data)
    .add_yaxis(series_name="预测产量", 
           is_smooth=True,
           y_axis=predicted_2024, 
           symbol_size=10, 
           label_opts=opts.LabelOpts(is_show=True))
    .set_global_opts(title_opts=opts.TitleOpts(title="2024年新能源汽车的月产量"),
                     xaxis_opts=opts.AxisOpts(type_='category', name="时间"),
                     yaxis_opts=opts.AxisOpts(type_='value', name="产量/万辆"),
                     )
)
predict_2024.load_javascript()
predict_2024.render_notebook()

        Over!晚安家人们,好梦啦~

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

施霁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值