R语言dynlm模型绘制预测区间时报错:下标越界
dynlm模型预测区间绘图报错及解决方案
问题概述
- 基于dynlm构建的模型可正常运行,但绘制带预测区间的可视化图时,触发错误:
Error in forecast$lower[, "95%"]: subscript out of bounds - 需求:为3/5/7天的预测结果添加80%、95%预测区间,并完成符合预期的绘图
数据样本
structure(list(Date = structure(c(19083, 19084, 19085, 19086, 19087, 19088, 19089, 19090, 19091, 19092, 19093, 19094, 19095, 19096, 19097), class = "Date"), US_Inflation_diff = c(-0.000219999999999998, -0.000189999999999996, 0.000099999999999989, -0.00000999999999998225, 0.00000999999999998225, -0.00000999999999999612, 0.00001000000000001, -0.0000000000000000138777878078145, -0.00000999999999998225, 0.00000999999999998225, -0.00000999999999999612, 0.00001000000000001, -0.00001000000000001, 0.00000999999999999612, -0.00000999999999998225 ), ATOM_12 = c(0, 2.002691, 0.570558999999999, -1.068854, -1.565735, -2.428472, 0.824852, -0.849135999999998, 0.406713, -0.688822000000002, -2.805074, 0.860166000000003, 0.0575009999999985, -0.731065999999998, 0.136664999999997)), row.names = c("2022-04-01", "2022-04-02", "2022-04-03", "2022-04-04", "2022-04-05", "2022-04-06", "2022-04-07", "2022-04-08", "2022-04-09", "2022-04-10", "2022-04-11", "2022-04-12", "2022-04-13", "2022-04-14", "2022-04-15"), class = "data.frame")
错误原因分析
- 列表索引逻辑错误:原代码中
forecast_list[[i/2]]的索引为非整数(i=3/5/7时,i/2=1.5/2.5/3.5),无法正确匹配列表元素,导致取到错误的forecast对象 - 预测区间数据源错误:原代码使用
forecast$x(训练集拟合值)拼接区间,而非预测期的区间数据,且未和预测期日期对齐 - 数据对齐错误:手动生成的
forecast_data日期与测试集真实日期不符,且US_Inflation_diff未使用测试集数据,导致预测结果无意义 - 绘图数据格式错误:
cbind生成的矩阵无明确列名,ggplot无法正确映射x轴和上下限
修正后的完整代码
library(dynlm) library(forecast) library(ggplot2) # 加载数据(假设数据已命名为data_2) data_2 <- structure(list(Date = structure(c(19083, 19084, 19085, 19086, 19087, 19088, 19089, 19090, 19091, 19092, 19093, 19094, 19095, 19096, 19097), class = "Date"), US_Inflation_diff = c(-0.000219999999999998, -0.000189999999999996, 0.000099999999999989, -0.00000999999999998225, 0.00000999999999998225, -0.00000999999999999612, 0.00001000000000001, -0.0000000000000000138777878078145, -0.00000999999999998225, 0.00000999999999998225, -0.00000999999999999612, 0.00001000000000001, -0.00001000000000001, 0.00000999999999999612, -0.00000999999999998225 ), ATOM_12 = c(0, 2.002691, 0.570558999999999, -1.068854, -1.565735, -2.428472, 0.824852, -0.849135999999998, 0.406713, -0.688822000000002, -2.805074, 0.860166000000003, 0.0575009999999985, -0.731065999999998, 0.136664999999997)), row.names = c("2022-04-01", "2022-04-02", "2022-04-03", "2022-04-04", "2022-04-05", "2022-04-06", "2022-04-07", "2022-04-08", "2022-04-09", "2022-04-10", "2022-04-11", "2022-04-12", "2022-04-13", "2022-04-14", "2022-04-15"), class = "data.frame") # 划分训练集和测试集(示例:前8天为训练集,后7天为测试集) train <- data_2[1:8, ] test <- data_2[9:15, ] # 拟合dynlm模型 dynlm_model_train_1 <- dynlm(ATOM_12 ~ US_Inflation_diff, data = train) # 生成不同天数的预测(指定80%、95%置信区间) forecast_3_1 <- forecast(dynlm_model_train_1, newdata = test[1:3, ], level = c(80, 95)) forecast_5_1 <- forecast(dynlm_model_train_1, newdata = test[1:5, ], level = c(80, 95)) forecast_7_1 <- forecast(dynlm_model_train_1, newdata = test[1:7, ], level = c(80, 95)) # 预测颜色向量 colors_vec <- c("steelblue", "orange", "purple") # 预测列表与天数对应 forecast_list <- list(forecast_3_1, forecast_5_1, forecast_7_1) day_list <- c(3,5,7) # 循环绘制每个预测图 for(idx in 1:length(day_list)){ i <- day_list[idx] forecast_obj <- forecast_list[[idx]] # 整理预测数据(使用测试集真实日期) forecast_data <- test[1:i, c("Date", "ATOM_12")] forecast_data$predicted <- forecast_obj$mean # 整理预测区间数据 pi_data <- data.frame( Date = test$Date[1:i], lower_80 = forecast_obj$lower[, "80%"], upper_80 = forecast_obj$upper[, "80%"], lower_95 = forecast_obj$lower[, "95%"], upper_95 = forecast_obj$upper[, "95%"] ) # 绘图 p <- ggplot() + # 历史数据曲线 geom_line(data = data_2, aes(x = Date, y = ATOM_12), color = "black", size = 1) + # 预测曲线 geom_line(data = forecast_data, aes(x = Date, y = predicted, color = "Forecast"), size = 1) + # 95%预测区间 geom_ribbon(data = pi_data, aes(x = Date, ymin = lower_95, ymax = upper_95), fill = "grey70", alpha = 0.5) + # 80%预测区间 geom_ribbon(data = pi_data, aes(x = Date, ymin = lower_80, ymax = upper_80), fill = "grey80", alpha = 0.5) + # 颜色设置 scale_color_manual(name = "", values = colors_vec[idx]) + # 主题与标签 theme_bw() + labs(x = "日期", y = "ATOM_12", title = paste(i, "天预测结果")) + # 历史数据线性趋势线 geom_smooth(data = data_2, aes(x = Date, y = ATOM_12), method = "lm", se = FALSE, color = "red") print(p) }
关键修正点说明
- 修正列表索引:使用整数索引遍历列表,确保正确匹配3/5/7天的预测对象
- 明确置信水平:在
forecast()函数中通过level = c(80,95)指定生成目标置信区间 - 数据对齐:直接使用测试集的真实日期和自变量数据,保证预测结果的合理性
- 结构化区间数据:将预测区间整理为包含日期的data.frame,方便ggplot直接映射
预期效果
绘图包含:
- 黑色的历史ATOM_12数据曲线
- 对应颜色的3/5/7天预测曲线
- 两层灰色的预测区间(深灰为95%置信区间,浅灰为80%置信区间)
- 红色的历史数据线性趋势线
内容的提问来源于stack exchange,提问作者talha asif
相关产品推荐
相关产品推荐

