
简介这份文档是一篇以ARIMA模型为核心的实证小论文面向正在学习时间序列分析与计量经济学的高校学生、科研入门者重点解决“如何利用Eviews软件对经济指标进行建模与预测”的问题。论文以我国1980—2012年全社会固定资产投资额为研究对象完整呈现了数据平稳性检验、差分处理、模型识别与参数估计、残差白噪声诊断以及2013年预测等环节最终给出ARIMA(4,1,3)模型的较优预测效果。全文共1个doc文件压缩包体积1.05MB内容紧凑适合用于课程论文参考、期末报告模仿或时间序列方法实战演练。已有253人学习下载对理解ARIMA建模流程、相关领域应用以及Eviews操作步骤均有直观帮助。文档还包含原始数据表、时序图、单位根检验结果等关键输出便于读者对照复现整个分析过程。1. 时间序列分析小论文的常见死法与选题定位“时间序列分析小论文.doc”这个标题大概率不是指某个固定工具而是很多人在课程作业、结课报告或季度数据分析里绕不过去的一个坎拿到一列带日期的数据要写出一篇能交差、能答辩、能说明白“数据里到底发生了什么”的文档。我见过太多初稿是同一副面孔开头一句“数据整体呈上升趋势”、中间一张折线图、结尾贴一个ARIMA预测R方或者RMSE一放就当结论。如果只是交差这确实够用但评阅的人只要多问一句“为什么差分一次而不是两次”“残差里还有没有可提取的信息”这套初稿基本就塌了。这篇内容按“从原始数据到可写进Word的完整推导链条”来组织覆盖平稳性、定阶、拟合、诊断、滚动验证这几个环节把每步该贴什么图、该写什么结论、该避开什么坑直接讲清楚。适合两类人一类是手头有一份带时间列的业务数据、需要快速产出分析报告的工程师另一类是正在写时序分析课程论文、想让自己那份报告从“套模板”升级成“可复现、可挑错”的学生。2. 时间序列分析的预处理与统计特征提取2.1 时间戳解析与索引排序拿到任何时序数据的第一步永远是把时间列变成真正的DatetimeIndex而不是字符串。很多人在Excel里看着日期很正常读进Pandas之后df[date]却是object类型直接用df.plot()画出来横轴就是乱序字符串。常见的处理方式是用parse_dates在读取时解析进内存后立刻排序并统一频率from pandas import read_csv, to_datetime df read_csv(sales.csv, parse_dates[date], index_coldate) df df.sort_index() # 检查索引是否有重复或缺失 print(df.index.duplicated().sum()) # 重复时间戳个数 print(df.index.is_monotonic_increasing) # 是否按时间递增 # 统一到日频无数据的日期填 NaN方便后续处理 df df.asfreq(D)parse_dates让Pandas把字符串解析成datetime64sort_index()必须放在检查之前因为后面所有关于“滞后”“差分”的操作都依赖时间顺序asfreq(D)会把数据重采样到日频原本缺失的日期显式变成NaN这一步不是为了好看而是为了后面做缺失值统计时有一个完整的时间轴。业务上如果原始数据本来就是工作日频率强行asfreq(D)会造出一大批周末空值这种情况应该用resample(B)或者干脆不重采样直接按原始时间戳建模。2.1.1 时间戳解析的边界情况时间列本身不干净的情况很常见有的是“2024/1/5 0:00”这种混着斜杠的有的是“20240105”八位数字还有的带时区后缀。统一用pd.to_datetime()手动兜底一次更稳妥df[date] to_datetime(df[date], formatmixed, errorscoerce) df df.dropna(subset[date])formatmixed允许同一列里出现多种日期格式errorscoerce把解析失败的记录置为NaN随后用dropna清掉。这一步看起来多此一举但实际数据里一条“2024-02-30”就能让后面的diff()结果出现莫名其妙的NaN断层排查成本远高于提前清理。2.2 缺失值处理与重采样小论文里常见的处理方式是df.fillna(df.mean())这在横截面数据里可以在时序数据里基本是错误示范。时间序列的缺失值不能用全局均值填充因为序列本身有趋势和季节性全局均值会把一个局部高值点拉向整体平均水平直接污染自相关结构。缺失比例推荐做法理由 5% 且呈孤立缺失线性插值interpolate(methodtime)按时间间隔插值尊重局部趋势连续缺失较长先按业务周期聚合再考虑模型补齐长段缺失时插值会“制造”数据高频数据中的零星空值前向填充ffill()多数业务指标可视为上一时刻延续# 按时间间隔线性插值 df[value] df[value].interpolate(methodtime) # 如果插值后仍有尾部缺失前向填充兜底 df[value] df[value].ffill().bfill()interpolate(methodtime)会利用DatetimeIndex的实际时间间隔来计算插值权重两个观测点间距越大插出来的值越接近较远的那一端这比methodlinear按行号插值更贴合业务直觉。ffill()和bfill()只做边界补齐不能作为主方案因为连续前向填充会在图像上制造一小段平台期ACF图里会出现“假拖尾”。2.3 趋势、季节性与残差的三方分解描述时间序列前先做一次STL分解这是性价比最高的一步。STL处理趋势和季节性时比单纯移动平均更稳健加了robustTrue后对异常值不那么敏感from statsmodels.tsa.seasonal import STL import matplotlib.pyplot as plt stl STL(df[value], period7, robustTrue).fit() fig stl.plot() plt.tight_layout() plt.savefig(stl_decompose.png, dpi150).plot()会输出四张子图原始序列、趋势项、季节项、残差项。period7对应周周期如果是月度数据观察年度周期这里应改成12如果拿不准周期可以对原始数据做周期图看看峰值出现在哪个频率。robustTrue会在迭代拟合里降低异常点权重适合销售、流量这类偶尔有促销或宕机尖刺的数据。2.3.1 分解结果怎么读观察趋势项判断是否存在单调变化这决定后面要不要给模型加trend项观察季节项是否长期稳定稳定则说明季节性可以用固定周期描述关键在残差项——如果残差里还有明显波动规律说明周期参数挑错了。不少小论文把分解图放上但不写结论评阅人看不到分析痕迹。写上三句判断比如“残差项的波动范围约在±0.3内未见明显周期结构可进入平稳性检验”整段分析的完整度立刻不一样。3. 时间序列平稳性检验与ARIMA定阶思路3.1 ADF单位根检验与差分次数大部分时序建模流程的第一步是判断序列是否平稳而判断平稳最常用的就是ADF检验。这里有一个容易翻车的地方ADF检验有regression参数默认是c只含常数项但序列如果有明显的线性趋势应该用ct常数项趋势项否则检验功效会下降原本平稳的趋势序列会被误判成有单位根。from statsmodels.tsa.stattools import adfuller adf_result adfuller(df[value], autolagAIC, regressionct) print(fADF统计量: {adf_result[0]:.4f}) print(fp值: {adf_result[1]:.4f})autolagAIC让函数自动选择最优滞后阶数避免手动定滞后影响检验结果。p值小于0.05可以认为拒绝单位根原假设序列平稳大于0.05则需要差分。对原始序列做一阶差分后再次检验直到通过为止diff1 df[value].diff().dropna() adf_diff1 adfuller(diff1, autolagAIC, regressionc) print(f一阶差分后p值: {adf_diff1[1]:.4f})提示小论文里切不要只写“差分后p值小于0.05”要写清楚差分次数、回归形式、滞后阶数这三个前提。同一个序列用regressionc和regressionct得到的结果可能相反。差分次数不能无限增加过差分会让序列丢失长期信息方差被放大。通常差到d1或d2就停d2在小论文里基本站不住脚评阅人会怀疑数据预处理环节出了问题。3.2 ACF和PACF拖尾/截尾怎么看差分成平稳序列后画ACF和PACF图这是ARIMA定阶最直观的一步。注意plot_acf和plot_pacf的lags参数数据量少于100时lags40会画出太多无关置信区间反而干扰判断from statsmodels.graphics.tsaplots import plot_acf, plot_pacf fig, axes plt.subplots(2, 1, figsize(10, 6)) plot_acf(diff1, axaxes[0], lagsmin(30, len(diff1) // 3)) plot_pacf(diff1, axaxes[1], lagsmin(30, len(diff1) // 3)) plt.tight_layout() plt.savefig(acf_pacf.png, dpi150)3.2.1 看图定阶的三种情况第一种ACF拖尾、PACF在滞后k阶处截尾对应AR(k)模型第二种ACF在滞后k阶处截尾、PACF拖尾对应MA(k)模型第三种ACF和PACF都拖尾说明纯ARIMA结构不够需要考虑SARIMA或对数据做变换。实际业务数据里第三种最常见所以不要在这里纠结太久靠信息准则辅助定阶是更省力的路线。3.3 信息准则辅助定阶小论文里不要只写一行auto_arima的结果评委想看的是“你比较过哪些候选模型”。用一个小网格搜索遍历参数组合把AIC、BIC记录下来形成一个可展示的候选表import itertools import warnings from statsmodels.tsa.statespace.sarimax import SARIMAX warnings.filterwarnings(ignore) results [] for p, d, q in itertools.product(range(3), [1], range(3)): try: model SARIMAX(diff1, order(p, d, q), trendn, enforce_stationarityFalse) fit model.fit(dispFalse) results.append((p, d, q, fit.aic, fit.bic)) except Exception: continue candidate_df pd.DataFrame(results, columns[p, d, q, AIC, BIC]) print(candidate_df.sort_values(AIC).head(5))enforce_stationarityFalse表示在拟合阶段不强求模型满足平稳条件交给数据自己判断这能减少迭代报错的概率trendn因为在差分上建模原序列的趋势已经由差分处理。按AIC升序取前5个候选再结合ACF/PACF图的判断做最终选择。候选模型AICBIC选择理由ARIMA(1,1,1)1023.41035.2AIC最小且从AR到MA各留一阶残差大概率噪声ARIMA(2,1,0)1025.11034.0模型更简洁BIC更优样本量小可考虑ARIMA(0,1,2)1028.91039.7仅做参考写进小论文时把这张表放进去结论写明“按AIC最小原则选择ARIMA(1,1,1)”后文所有预测都基于这个模型全篇就有一条完整的决策链。4. 时间序列模型拟合、诊断与滚动验证4.1 划分训练集与测试集时序预测不能用随机拆分只能用前段训练、后段验证。拆分的比例取决于预测量级如果能观测到的历史数据足够长可以留出最后10%做验证如果样本量特别小留出20%会导致训练集信息不足。一个相对稳妥的做法是先看数据总量少于200个观测时留10%即可。n_test int(len(df[value]) * 0.1) train df[value].iloc[:-n_test] test df[value].iloc[-n_test:]注意iloc切分前要确认索引已经按时间排序否则切出来的一段可能时间不连续。切分后看一眼train.index[-1]和test.index[0]确认没有断开或错位。4.2 SARIMAX拟合与关键参数说明定好阶数后正式拟合模型。数据里有明显周季节性时用SARIMA而不是纯ARIMA季节周期m要和前面STL分解时用的period保持一致from statsmodels.tsa.statespace.sarimax import SARIMAX model SARIMAX(train, order(1, 1, 1), seasonal_order(0, 1, 1, 7), trendc, enforce_stationarityFalse, enforce_invertibilityFalse, time_varying_regressionFalse) fit model.fit(dispFalse) print(fit.summary())order(1,1,1)中的三个数字分别对应非季节部分的AR阶数、差分次数、MA阶数与3.3节里选的阶数一致。seasonal_order(0,1,1,7)中前三个数字是季节部分对应的阶数最后的7是季节周期长度这是SARIMA和ARIMA最关键的区别。trendc表示在模型里加入常数漂移项适合有明显长期增长但已经差分过一遍的序列。注意enforce_stationarity和enforce_invertibility两个参数在拟合阶段应保持默认关闭遇到优化器收敛告警时优先检查阶数是否过大而不是直接改这两个参数。4.3 残差诊断模型拟合完不能只看预测准不准得先确认残差是白噪声。这里用Ljung-Box检验from statsmodels.stats.diagnostic import acorr_ljungbox resid fit.resid lb_test acorr_ljungbox(resid, lags[7, 14, 21], return_dfTrue) print(lb_test)lags[7, 14, 21]三个滞后阶分别对齐一周、两周、三周周期能够捕获周期内残留的自相关。return_dfTrue让输出变成DataFrame直接看lb_pvalue列全部大于0.05则残差无显著自相关模型结构抓干净了。如果有某个阶数的p值小于0.05回到3.3节调整阶数或者考虑加大季节部分阶数。残差方差是否稳定也很重要。画出标准化残差图观察是否在某段区间出现“喇叭口”形状plt.figure(figsize(10, 3)) plt.plot(resid / resid.std()) plt.axhline(y0, colorblack, linestyle--, linewidth0.8) plt.savefig(resid_std.png, dpi150)如果残差分段的波动幅度差异明显说明方差不稳定常见做法是对原始数据做log1p变换后重新走一遍流程。4.4 滚动验证评估稳定性小论文里放一个总体的RMSE会显得单薄因为单次划分训练/测试集的结果受切分点位置影响很大。更常用的做法是做滚动一步预测逐点评估模型在每一步的误差import numpy as np from sklearn.metrics import mean_absolute_error, mean_squared_error history list(train.values) predictions [] for t in range(len(test)): model SARIMAX(history, order(1, 1, 1), seasonal_order(0, 1, 1, 7), trendc, enforce_stationarityFalse) fit model.fit(dispFalse) yhat fit.forecast(steps1).iloc[0] predictions.append(yhat) history.append(test.values[t]) # 把真实值加进历史模拟在线更新 mae mean_absolute_error(test.values, predictions) rmse np.sqrt(mean_squared_error(test.values, predictions)) print(fMAE: {mae:.4f}, RMSE: {rmse:.4f})这一步循环每迭代一次就重新拟合模型计算开销比一次性拟合高出不少但换来的是稳定的误差曲线。把每步的yhat和真实值存下来画成“预测值对比测试值”的折线图比只报一个RMSE更能说明问题。5. 时间序列预测结果的可视化与可复现输出5.1 让matplotlib出图直接能放进Word默认的matplotlib中文字体会在Word里变成一串方块。在画图脚本顶部统一配置import matplotlib matplotlib.rcParams[font.sans-serif] [SimHei, Microsoft YaHei, Arial Unicode MS] matplotlib.rcParams[axes.unicode_minus] False plt.rcParams[figure.dpi] 150axes.unicode_minusFalse用来修正负号显示成方框的问题。figure.dpi150保证导出图的清晰度Word页面宽度有限figsize(8, 4)左右的图在文档里最协调长宽比太大会被缩放导致字看不清。5.2 把DataFrame导出成Word可粘贴的三线表表格直接从DataFrame截屏放进Word很丑而且以后数据更新了还要重新截。最省事的方式candidate_df.round(2).to_clipboard()执行后直接到Word里粘贴成表格再手动加上下粗线、表头细线做成三线表。这个操作在Excel或WPS里同样适用比导出为图片再插入要干净得多。如果表格列数多可以先用.T转置再复制超过八列的宽表在Word里横排会被截断。5.3 把所有关键参数集中到一个配置区做完整轮分析后把会变的参数统一提到脚本顶部这样小论文里所有图表都可以在一分钟以内重新生成CONFIG { data_path: sales.csv, date_col: date, value_col: value, freq: D, period: 7, adf_regression: ct, order: (1, 1, 1), seasonal_order: (0, 1, 1, 7), trend: c, train_ratio: 0.9, lags: [7, 14, 21], }接下来所有脚本都引用CONFIG[order]、CONFIG[period]而不是写成固定数字。评审问“为什么用7不用8”的时候直接改CONFIG[period] 8重跑一遍对比两张图远比现场翻代码找参数再重新执行一整套分析要从容。整套流程跑完从数据解析、平稳性检验到模型诊断、滚动预测每一步都能对应上脚本中的一段代码和一份输出这篇小论文就不再是“抄一个模板”而是一套随时可以重放的分析管道。本文还有配套的精品资源点击获取