You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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")

错误原因分析

  1. 列表索引逻辑错误:原代码中forecast_list[[i/2]]的索引为非整数(i=3/5/7时,i/2=1.5/2.5/3.5),无法正确匹配列表元素,导致取到错误的forecast对象
  2. 预测区间数据源错误:原代码使用forecast$x(训练集拟合值)拼接区间,而非预测期的区间数据,且未和预测期日期对齐
  3. 数据对齐错误:手动生成的forecast_data日期与测试集真实日期不符,且US_Inflation_diff未使用测试集数据,导致预测结果无意义
  4. 绘图数据格式错误: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)
}

关键修正点说明

  1. 修正列表索引:使用整数索引遍历列表,确保正确匹配3/5/7天的预测对象
  2. 明确置信水平:在forecast()函数中通过level = c(80,95)指定生成目标置信区间
  3. 数据对齐:直接使用测试集的真实日期和自变量数据,保证预测结果的合理性
  4. 结构化区间数据:将预测区间整理为包含日期的data.frame,方便ggplot直接映射

预期效果

绘图包含:

  • 黑色的历史ATOM_12数据曲线
  • 对应颜色的3/5/7天预测曲线
  • 两层灰色的预测区间(深灰为95%置信区间,浅灰为80%置信区间)
  • 红色的历史数据线性趋势线

内容的提问来源于stack exchange,提问作者talha asif

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 20:37:01