news 2026/9/24 19:27:07

时间序列预测Python实战:三个经典数据集跑通ARIMA与SARIMA

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
时间序列预测Python实战:三个经典数据集跑通ARIMA与SARIMA

简介:面向 Python 时间序列预测初学者与分析人员,这份代码资源覆盖金融、气象、销售等常见时序场景,系统演示 Pandas 预处理、ARIMA/SARIMA 建模、状态空间方法、Prophet 以及机器学习模型的应用。压缩包共 214 个文件,含 181 个可运行 Python 脚本、32 个 CSV 示例数据和 1 份说明文档,合计 237KB,结构清晰、便于按模块查阅;脚本与数据配套,可完整走通从加载、清洗、建模到评估的流程。目前已有 7257 人学习,资源使用每日最低气温、太阳黑子、每日出生人数等经典数据集,帮助理解趋势、季节性和 MSE/RMSE 等评估指标。适合希望通过实际代码快速上手时间序列分析与预测的读者,是一份实用且轻量的入门参考资料。

1. 时间序列预测的 Python 配套代码:先跑通再谈调参

在 Python 里做时间序列预测,最大的门槛从来不是 ARIMA 的公式,而是「数据摆在你面前,第一步该干什么」。这份名为 Code for Introduction to Time Series Forecasting with Python 的压缩包,整理了时间序列预测入门最经典的三份数据集和配套代码——每日最低气温、太阳黑子数、每日女婴出生数,覆盖了趋势、季节性、周期性、随机波动这些你在任何教材里都会碰到的数据形态。如果你正打算用 Python 做预测分析,又不想从零开始拼装数据预处理和模型调参的流程,这份 code 资源能帮你省掉大量搭骨架的时间。它适合刚接触 pandas 时间索引、想知道 ARIMA 和 SARIMA 到底怎么落地的人,也适合已经跑过模型、但想在数据集选择上补一课的一线分析岗。

2. 三个数据集先看明白:温度、太阳黑子与出生人数的建模策略差异

很多下载这份资源的人第一反应是直接跑 ARIMA,但真正决定预测效果的不是模型,而是你手里这份数据长什么样。压缩包里的三个 CSV 分别代表三种完全不同的时间序列形态,建模策略也因此分道扬镳。

2.1 每日最低气温:年度季节性是一切判断的起点

daily-minimum-temperatures.csv 记录的是墨尔本 1981 至 1990 年每天的最低气温,暂时不看具体数值,单从业务直觉就能判断:冬季气温低、夏季气温高,这个序列必然存在以一年为周期的强季节性。它的索引是日期字符串,格式类似1981-01-01,总共 3650 行,没有缺失值。

import pandas as pd df_temp = pd.read_csv( "daily-minimum-temperatures.csv", parse_dates=[0], # 把第一列解析为日期 index_col=0, # 用日期列做行索引 header=0, # 第一行是列名 names=["date", "temp"] # 显式指定列名,避免文件头干扰 ) print(df_temp.head()) print(df_temp.index)

这里有个容易被忽略的细节:parse_dates=[0]只是让 pandas 把字符串转成 Timestamp 对象,真正让时序分析工具生效的是后面的index_col=0。ARIMA 这类模型在 statsmodels 里通常要求索引是 DatetimeIndex 或 PeriodIndex,如果你留着默认的 RangeIndex 跑plot_acfseasonal_decompose,很多函数也能跑,但结果里的周期信息是错的。

从建模角度看,这份数据适合演示「先分解、再建模」的完整流程。你可以用seasonal_decompose把序列拆成趋势、季节、残差三部分,温度数据的季节项曲线平滑且规律,是理解 SARIMA 里季节性参数m=365到底在拟合什么的最佳样例。它的缺点也明显:数据量 3650 行不算小,但如果你想跑带年度季节性的 SARIMA,模型参数会非常多,拟合时间会长到让人怀疑人生——这一点后面第 4 章专门讲。

2.2 太阳黑子数据:周期性与季节性的本质区别

sunspots.csv 是 1700 到 1988 年每年记录的太阳黑子数,每年一行,一共 289 条。它和温度数据最大的不同在于:太阳黑子有约 11 年的准周期,但这个周期不是固定长度的季节性,而是「平均 11 年一次、实际可能 9 到 13 年浮动」的周期性。这两者在统计学上是两回事,季节性适合用 SARIMA 的季节分量去拟合,周期性则需要靠差分或不依赖固定周期的模型。

df_sun = pd.read_csv( "sunspots.csv", parse_dates=[0], index_col=0, header=0, names=["date", "sunspots"] ) print(df_sun.shape) # 只有 289 行 print(df_sun.head(3))

这份数据样本量小,但信噪比高——太阳黑子的波动幅度远大于随机噪声,所以你拿它练手时,模型预测的曲线通常能贴合真实值的大致走向。它也是理解平稳性概念的好样本:从肉眼上看序列有明显波动,但 ADF 检验的 p 值经常落在 0.05 以下,给人一种「这个序列已经平稳」的错觉,其实是因为周期长度接近样本长度的一半,检验统计量被拉偏了。这种反直觉的情况,恰恰是你理解单位根检验边界的最佳教材。

2.3 每日女婴出生数:短样本下的周期性陷阱

daily-total-female-births.csv 记录 1959 年每天加州出生的女婴数,只有 365 行。数据量小到任何复杂的季节性模型都跑不动,但它的特征是:存在以 7 天为周期的星期效应——周末出生数显著低于工作日。这为 SARIMA 的m=7季节性参数提供了一个理想的小规模演示场景。

df_birth = pd.read_csv( "daily-total-female-births.csv", parse_dates=[0], index_col=0, header=0, names=["date", "births"] ) # 按星期几分组看均值差异 df_birth["weekday"] = df_birth.index.dayofweek print(df_birth.groupby("weekday")["births"].mean().round(1))

跑完这段代码你通常能看到:周日出生数均值明显低于周中,而周六略低。这个 7 天周期的存在意味着 SARIMA 的seasonal_orderm可以设成 7,模型只需要 365 个样本就能拟合完整参数。如果你不看数据直接套用季节分解,或者把m设成 365,就会得到一份残差全是 NaN 的输出——因为季节周期长度等于样本长度时,分解函数根本算不出季节分量。这就是短样本数据最有教学价值的地方:它逼迫你意识到,季节周期的前提是数据里至少包含多个完整的周期。

数据集样本量时间粒度主要特征适合模型
daily-minimum-temperatures3650年度强季节 + 缓慢趋势SARIMA、Prophet、STL 分解
sunspots289约 11 年准周期,非固定节律ARIMA(差一阶)、状态空间
daily-total-female-births365星期周期效应,短样本SARIMA(m=7)、ETS

这三个数据集在压缩包里各有各的用场,你可以把它们当成三个独立的练手项目串行跑。很多初学者把注意力全放在模型代码上,忽略了数据集本身的差异,结果就是同一段脚本换份数据就不出结果,然后怀疑自己代码写错了。实际上数据形态决定了你该走哪条建模路径,这个判断顺序比调参重要得多。

3. 平稳性处理:为什么差分是多数预测代码的第一步

时间序列预测的教材会把平稳性讲得很抽象,但落到这份资源的代码里,它的作用非常直接:ARIMA 模型里的「I」就是差分,而差分的目标是把非平稳序列转成平稳序列,让自回归和滑动平均部分可以正常工作。如果跳过这一步,模型的预测结果容易出现离谱的漂移或直接退化成均值预测。

3.1 平稳性的判断:ADF 检验和你的眼睛哪个更靠谱

statsmodels 提供adfuller函数来做单位根检验,零假设是「序列存在单位根,即非平稳」。当 p 值小于 0.05 时拒绝原假设,认为序列平稳。但实际处理数据时,单纯看 p 值很容易踩坑。

from statsmodels.tsa.stattools import adfuller for name, series in [ ("temp", df_temp["temp"]), ("sunspots", df_sun["sunspots"]), ("births", df_birth["births"]) ]: result = adfuller(series.dropna()) print(f"{name}: ADF = {result[0]:.3f}, p-value = {result[1]:.4f}")

跑出来的结果通常会让新手困惑:太阳黑子序列的 p 值经常显著小于 0.05,按检验标准它「平稳」,但画图看它明明有明显起伏——这是太阳黑子数据最经典的统计误解。原因是它的周期大约 11 年,而样本只有 289 年,检验统计量在接近周期长度的低频成分面前会失真。我的经验是:ADF 检验结果只是参考坐标,真正靠谱的是结合可视化和业务知识。温度数据视觉上有年度周期,太阳黑子数据视觉上有约 11 年的波动,出生人数数据有明显的周内升降——这三者都不满足严格平稳性的要求,但差分策略完全不同。

温度数据用一阶差分就能把趋势去掉,但季节性还在;太阳黑子数据差一阶后波动幅度会减小,但准周期依然存在;出生数据本身均值稳定,只是方差有波动。把adfuller的 p 值和序列的 ACF 图放一起看,比单独依赖任何一个都稳妥。实际操作中我一般会先画滚动均值线(比如df.rolling(30).mean())观察均值是否随时间漂移,再跑 ADF 验证,两步互相印证。

3.2 差分操作的边界:差一阶就够还是差到无能为力

statsmodels 里的diff()是 pandas 内置方法,默认periods=1。一阶差分计算的是相邻两个时间点的差值,它的作用是消除线性趋势;如果序列存在二次趋势,可能需要二阶差分。但对这三个数据集来说,二阶差分基本没有意义——温度数据在一阶差分后均值已经稳定在零附近,再差一阶只是放大噪声。

temp_diff1 = df_temp["temp"].diff().dropna() sun_diff1 = df_sun["sunspots"].diff().dropna() # 观察差分后的均值是否接近零 print(temp_diff1.mean()) print(sun_diff1.mean()) # 如果你想对比差分前后的方差变化 print(df_temp["temp"].var(), temp_diff1.var())

差分后均值为零说明趋势被移除,但方差变化也需要关注。一个常见的错误是:不分青红皂白对每个序列都做二阶差分,以为差分次数越多越「平稳」。实际情况是,差分过度会消除掉模型需要的长期依赖信息,让 ACF 出现假性的负相关,导致 ARIMA 定阶时pq被过度估计。对 sunspots 数据,我曾经试过二阶差分,结果 ARIMA 模型的 AIC 反而比一阶差分高了几十个点,预测曲线也变得更加锯齿状。

另外一个容易忽略的边界是差分的对齐问题。diff()返回的第一个值是 NaN,必须dropna()才能喂给模型。如果你忘记丢弃第一行,后续的 ACF 图和模型拟合都会报错,报错信息往往还很不直观——这是这个资源里最容易让新手卡住的第一个坑。

4. ARIMA 与 SARIMA 实战:定阶、调参与四类高频报错排查

这一章是整套代码的主干。利用前面的预处理结果搭建 ARIMA 模型并做预测,同时把你在实际运行中最有可能遇到的报错和异常结果集中排查一遍。这里讲的坑不是理论推演,而是这份资源在本地跑一遍几乎必现的问题。

4.1 ACF 和 PACF 定阶:先看图再让 auto_arima 兜底

ARIMA 模型有三个核心参数:p(自回归阶数)、d(差分阶数)、q(滑动平均阶数)。d在第 3 章已经确定,pq需要借助 ACF(自相关函数)和 PACF(偏自相关函数)图判断。ACF 图在滞后阶数之后截尾,说明需要滑动平均项;PACF 图截尾说明需要自回归项。

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf import matplotlib.pyplot as plt temp_diff = df_temp["temp"].diff().dropna() fig, axes = plt.subplots(2, 1, figsize=(10, 6)) plot_acf(temp_diff, lags=40, ax=axes[0]) plot_pacf(temp_diff, lags=40, ax=axes[1]) plt.show()

这是标准的看图定阶流程,但实际执行时有个问题:ACF 图在滞后 365 处会出现一个明显的峰值,提醒你年度季节性没有完全被一阶差分移除。此时如果直接按 ACF 的短期表现定pq,模型预测效果会打折扣。正确做法是,对含季节性的序列直接跳过纯 ARIMA,改用 SARIMA——或者先对序列做季节差分(比如df.diff(365))再定阶。

懒人做法是直接上pmdarima库的auto_arima,让它按 AIC 准则自动搜索参数组合:

from pmdarima import auto_arima model = auto_arima( df_temp["temp"].dropna(), start_p=0, max_p=5, start_q=0, max_q=5, d=1, seasonal=True, m=365, # 年度季节性周期 trace=False, error_action="ignore", suppress_warnings=True, stepwise=True, ) print(model.order, model.seasonal_order)

m=365是温度数据的正确季节周期,但它会让搜索过程极慢——因为季节性差分需要计算跨 365 步的差值,每个候选参数组合都要做一次完整的拟合。我第一次跑这个搜索花了将近 15 分钟,差点以为程序卡死了。如果你只是想快速验证流程,可以把m临时改成 7 跑通,或者把stepwise保持为 True 减少搜索空间。这个m的合理值是后续预测效果的分水岭,别随意填。

4.2 SARIMA 季节性参数设置:m 不是越大越好

SARIMA 在 ARIMA 基础上多了四个参数:PDQm。其中m是季节周期长度,D是季节性差分的阶数,PQ是季节性自回归和滑动平均的阶数。模型结构变成SARIMA(p,d,q)(P,D,Q)m

from statsmodels.tsa.statespace.sarimax import SARIMAX model = SARIMAX( df_temp["temp"], order=(1, 1, 1), seasonal_order=(1, 1, 1, 365), enforce_stationarity=False, enforce_invertibility=False, ) fitted = model.fit(disp=False) print(fitted.aic)

seasonal_order是一个四元组,最后一个元素就是m。这里最核心的建议是:对温度数据,理论上的季节周期m=365,实际拟合时经常因为计算量过大而没法收敛。我的习惯做法是折中——要么降采样到月粒度后设m=12,要么保留日粒度但接受拟合时间较长。强行跑m=365的日粒度模型,训练时间动辄几十秒起,预测 30 天的未来值精度提升却非常有限。如果样本本身只有一年,比如女婴出生数据,m=7是唯一合理的选择,设 365 的话模型会因为样本量不足以估计季节性参数而直接报维度错误。

4.3 高频排查:四个报错和它的修复路径

报错一:InvertibilityWarning: Non-invertible starting MA parameters found

现象:提示非可逆的 MA 初始参数,拟合输出一堆 nan。

原因:模型对初始参数的选择过敏,多半是pq阶数定的太大,或者数据里存在较强的离群值干扰了初始迭代。

解决:在SARIMAX里显式传入method_kwargs限制初始参数范围,或者改用auto_arima给出的更保守的阶数。最直接的技巧是给order用更小的值,比如(1,1,1)替换(3,1,3)

报错二:ValueError: Pandas data cast to numpy dtype of object. Check input data with python pd.api.types.is_numeric_dtype

现象:模型拟合报错,提示数据类型不是数值型。

原因:CSV 文件里混入了空字符串或者注释行,pandas 读进来后整列变成了 object 类型。这个坑在 sunspots.csv 这种老数据里比较常见。

解决:读取时用error_bad_lines=False跳过坏行,或者读入后用pd.to_numeric(series, errors='coerce')强制转换,再dropna()去掉转换失败的行。

报错三:预测结果是一条水平直线

现象:模型拟合没报错,但 predict 画出来的未来 30 天是一条近似水平的直线。

原因:这不是代码错误,而是 ARIMA 模型的数学特性——它对长期预测会收敛到序列的均值。温度数据在一年尺度上确实存在季节性,但如果你只跑 ARIMA 而不是 SARIMA,模型没有能力感知季节周期,预测自然退化成均值直线。

解决:换成 SARIMA 并正确设置m;如果只想用 ARIMA,就把预测步长缩短到几天的尺度,滚动预测的效果远好于一次性预测 30 天。

报错四:ValueError: The number of observations must be larger than the maximum lag

现象:跑 ACF 或拟合 SARIMA 时宝观测数不足。

原因:数据里 NaN 没有被正确去掉,或者样本量小于滞后阶数。对只有 365 行的出生数据,如果你设lags=40的 PACF 没问题,但设lags=300就会触发这个报错。

解决:做dropna()之后再计算,并且把滞后阶数控制在样本量的十分之一以内。

这些报错在三个数据集上几乎轮流出现一遍。尤其是温度数据的水平直线预测,很多第一次跑的人以为模型学废了,实际上只是模型选错了——用 SARIMA 之后同样的代码立刻能输出带季节起伏的预测曲线。排查时不要从头到尾重写代码,先确认 d 和 m 两个参数,再检查数据格式,90% 的问题出在这两个环节。

5. 预测验证的习惯:评估指标之外的三个检查动作

模型拟合完成后,评估指标只是第一步。MSE、RMSE、MAE 这些指标能告诉你误差大小,但它们无法告诉你「模型是否学到了数据里的结构」。我的习惯是留出最后 10% 的数据做验证集,跑完模型后额外做三个检查。

5.1 残差图与自相关检查

残差是预测值和真实值的差,理想残差应该是白噪声——均值接近零,ACF 图没有显著的相关峰值。如果残差里还有明显的周期结构,说明模型的季节性参数没有捕捉干净。

resid = fitted.resid.dropna() plot_acf(resid, lags=40) plt.show()

如果 ACF 图中滞后 7 或滞后 365 处出现显著尖峰,说明你在seasonal_order里漏掉了这个周期。对出生数据,滞后 7 处的尖峰意味着你没设m=7的季节项。

5.2 滚动预测比对一次性预测更可靠

一次性预测未来 N 步的误差会随步长增大迅速膨胀。做滚动预测:每预测一天就拿真实值替换,再预测下一天,这样得到的 RMSE 更接近模型的实际业务表现。

history = df_birth["births"].values[:-30] predictions = [] for t in range(30): model = SARIMAX(history, order=(1,1,1), seasonal_order=(0,1,1,7)) fitted = model.fit(disp=False) pred = fitted.forecast(1)[0] predictions.append(pred) history = np.append(history, df_birth["births"].values[-30 + t])

滚动预测的每次拟合都消耗时间,但它能暴露模型在连续预测中的衰减速度,这个信息一次性预测给不了。

5.3 预测区间比点预测更有业务参考价值

SARIMAX 的get_forecast方法同时返回置信区间,区间宽度反映了模型对预测的不确定性。如果区间宽度等于零或者窄得异常,基本可以断定模型过拟合了。真实业务里,比起「明天 13.2 度」这个点,更常需要的是「明天 8 到 18 度」的区间。

从我的经验看,这套 zip 里的代码价值不止在于可运行的 ARIMA 示例,更在于三个数据集搭配着练一遍之后,你会形成一套判断数据形态的直觉。拿到一份新数据,先看样本量,再画图确认有没有季节性和趋势,然后决定差分阶数和模型结构——这套动作我在跑完这个资源之后才真正固化下来。从那以后,我每次处理新时序数据都强制先跑一遍「可视化分解、差分检验、残差复查」三件套,不再一上来就调 auto_arima。这份配套代码适合在本地跑通一遍,你会发现从数据加载到预测评估全流程走完,比单独啃一章教材有效得多。希望这篇拆解能帮你更快跑通它。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/24 19:26:56

手机卡顿真相:存储空间与运行内存的区别与清理指南

1. 为什么“清理手机”成了当代人的日常仪式?你有没有过这种体验:刚换的新机用半年,微信一开就转圈,拍照要等三秒才出预览,刷短视频卡成PPT,连扫码付款都要多扫两次?不是手机老了,是…

作者头像 李华
网站建设 2026/9/24 19:26:15

鸿蒙Flutter集成googleapis_beta:跨平台云API调用实战指南

1. 项目背景与目标拆解1.1 为什么要在鸿蒙上引入 googleapis_beta我最初接触这个任务,是在一个跨平台物联网项目的中期。业务侧提出要接 Google Cloud 的 Beta 接口,用来做设备消息的预测分析和自动扩缩容调度。当时我们整个客户端已经跑在 Flutter 上&a…

作者头像 李华
网站建设 2026/9/24 19:26:12

Windows 11桌面图标闪烁排查指南:资源管理器、注册表与显卡驱动

桌面图标每隔几秒集体闪一下,鼠标右键菜单刚弹出来就消失,任务栏跟着一起抽风——这个场景我在过去两年里至少遇到过七八次,涉及的都是 Windows 11 环境,机器从轻薄本到工作站都有。很多人第一反应是重装系统,其实大可…

作者头像 李华
网站建设 2026/9/24 19:23:54

企业AI服务化落地指南:AI应用架构师如何做好API设计

上个月和一位做制造业信息化的朋友聊天,他提到一个很典型的困境:公司买了大模型平台的账号,研发团队也陆续做了几个AI改造的demo,但一提到接入正式生产系统,每个业务线就开始各写各的调用代码。有人把模型密钥直接放到…

作者头像 李华
网站建设 2026/9/24 19:21:27

毕业就业信息管理系统开发实战:Spring Boot + MyBatis Plus 全栈方案

每年到了毕业季,都能在校园里看到同一幕场景:学生在各种微信群里被动接收零散的就业信息,企业HR一边抱怨收不到合适的简历,一边在多个平台重复发布岗位。作为一个做过几年Java开发、又回来带过几届毕设的人,我可以直接…

作者头像 李华
网站建设 2026/9/24 19:20:54

Spring Boot 3 + Vue 3 社团管理系统全栈开发实战

最近很多初学全栈的朋友问我同一个问题:想做一个能真正上线的管理系统,但不知道从哪下手。正好我前阵子帮学校的社团联合会搭过一套管理系统,技术栈就是标题里写的 Spring Boot 3 Vue 3,从需求分析到部署上线完整走了一遍。这系统…

作者头像 李华