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

将年度时间序列预测函数适配为月度版本的技术问题

问题背景

现有可用于年度时间序列预测的R语言函数,需修改为支持月度时间序列预测的版本。

现有年度预测函数代码

library(forecast)
library(zoo)

set.seed(289805)
y <- arima.sim(n = 10, model = list(ar = 0.8, order = c(1, 0, 0)), sd = 1)
y <- ts(y, frequency = 1, start = c(1981))


#-- 提取训练数据、拟合模型并生成预测
yt <- window(y, end = 1990)

#yfit <- Arima(yt,order = c(3, 1, 4))
yfit <- forecast::auto.arima(yt)

yfor <- forecast(yfit)

#--- 提取ggplot可用数据的函数funggcast()
funggcast <- function(dn, fcast){

  en <- max(time(fcast$mean)) # 提取预测用到的最大日期

  # 提取源数据和训练数据
  ds <- as.data.frame(window(dn, end = en))
  names(ds) <- 'observed'
  ds$Year <- as.Date(time(window(dn, end = en)))

  # 提取拟合值(需解决置信区间提取问题)
  dfit <- as.data.frame(fcast$fitted)
  dfit$Year <- as.Date(time(fcast$fitted))
  names(dfit)[1] <- 'fitted'

  ds <- merge(ds, dfit, all.x = T) # 将拟合值与源数据、训练数据合并

  # 提取预测值和置信区间
  dfcastn <- as.data.frame(fcast)
  dfcastn$Year <- as.Date(paste(row.names(dfcastn), "01", "01", sep = "-"))
  names(dfcastn) <- c('forecast', 'lo80', 'hi80', 'lo95', 'hi95', 'Year')

  pd <- merge(ds, dfcastn, all = T) # 生成ggplot可用的最终数据框
  return(pd)

}

pd <- funggcast(y ,yfor)

pd

尝试的月度预测修改代码

library(forecast)
library(zoo)

set.seed(289805)
y <- arima.sim(n = 10, model = list(ar = 0.8, order = c(1, 0, 0)), sd = 1)
y <- ts(y, frequency = 12, start = c(1981, 1))


#-- 提取训练数据、拟合模型并生成预测
yt <- window(y, end = c(1981, 10))

#yfit <- Arima(yt,order = c(3, 1, 4))
yfit <- forecast::auto.arima(yt)

yfor <- forecast(yfit)

#--- 提取ggplot可用数据的函数funggcast()
funggcast <- function(dn, fcast){

  en <- max(time(fcast$mean)) # 提取预测用到的最大日期

  # 提取源数据和训练数据
  ds <- as.data.frame(window(dn, end = en))
  names(ds) <- 'observed'
  ds$Year <- as.Date(time(window(dn, end = en)))

  # 提取拟合值(需解决置信区间提取问题)
  dfit <- as.data.frame(fcast$fitted)
  dfit$Year <- as.Date(time(fcast$fitted))
  names(dfit)[1] <- 'fitted'

  ds <- merge(ds, dfit, all.x = T) # 将拟合值与源数据、训练数据合并

  # 提取预测值和置信区间
  dfcastn <- as.data.frame(fcast)
  dfcastn$Year <- as.Date(paste(row.names(dfcastn), "01", "01", sep = "-"))
  names(dfcastn) <- c('forecast', 'lo80', 'hi80', 'lo95', 'hi95', 'Year')

  pd <- merge(ds, dfcastn, all = T) # 生成ggplot可用的最终数据框
  return(pd)

}

pd <- funggcast(y ,yfor)

pd

报错信息

Error in charToDate(x) :
character string is not in a standard unambiguous format
In addition: Warning messages:
1: In window.default(x, ...) : 'end' value not changed
2: In window.default(x, ...) : 'end' value not changed

预期需求

需将输出数据框中的Year列替换为Year/Month列,生成包含1981年1月至1982年8月的月度数据,包含观测值、拟合值、预测值及对应置信区间,格式示例如下:

#    Year/Month   observed     fitted  forecast       lo80     hi80      lo95     hi95
#1  1981-01-01 -0.2505125 -0.1002050        NA         NA       NA        NA       NA
#2  1981-02-01  0.8855338 -0.2004100        NA         NA       NA        NA       NA
#...(省略后续行)

解决方案

报错核心原因是月度时间序列的time()返回值为带小数的数值(如1981.083代表1981年2月),直接转换为Date类型会失败,同时window函数对月度序列使用数值型end参数会触发警告。以下是修正后的完整代码:

library(forecast)
library(zoo)

set.seed(289805)
# 生成10个月度观测值,后续预测扩展至1982年8月(共20个时间点)
y <- arima.sim(n = 10, model = list(ar = 0.8, order = c(1, 0, 0)), sd = 1)
y <- ts(y, frequency = 12, start = c(1981, 1))

# 提取训练数据(1981年1-10月)
yt <- window(y, end = c(1981, 10))

# 自动拟合ARIMA模型,预测10个月(覆盖至1982年8月)
yfit <- forecast::auto.arima(yt)
yfor <- forecast(yfit, h = 10)

# 修正后的funggcast函数,支持月度时间序列
funggcast <- function(dn, fcast){
  # 将时间转换为yearmon格式,适配月度序列
  en <- max(as.yearmon(time(fcast$mean)))
  
  # 提取源数据和训练数据
  ds <- as.data.frame(window(dn, end = en))
  names(ds) <- 'observed'
  # 转换为YYYY-MM-01格式的日期,作为Year/Month列
  ds$`Year/Month` <- as.Date(as.yearmon(time(window(dn, end = en))))

  # 提取拟合值
  dfit <- as.data.frame(fcast$fitted)
  dfit$`Year/Month` <- as.Date(as.yearmon(time(fcast$fitted)))
  names(dfit)[1] <- 'fitted'

  # 合并拟合值与源数据
  ds <- merge(ds, dfit, all.x = TRUE)

  # 提取预测值和置信区间
  dfcastn <- as.data.frame(fcast)
  # 处理预测结果的行名,转换为标准日期格式
  dfcastn$`Year/Month` <- as.Date(as.yearmon(row.names(dfcastn)))
  names(dfcastn) <- c('forecast', 'lo80', 'hi80', 'lo95', 'hi95', 'Year/Month')

  # 合并所有数据并按时间排序
  pd <- merge(ds, dfcastn, all = TRUE)
  pd <- pd[order(pd$`Year/Month`), ]
  rownames(pd) <- NULL
  return(pd)
}

# 生成最终结果
pd <- funggcast(y ,yfor)
print(pd)

关键修正说明

  1. 时间格式适配:用zoo包的as.yearmon()将数值型时间转换为年月格式,再转为Date类型(自动设为每月1号),解决日期转换报错问题。
  2. window参数优化:使用yearmon类型的end参数,消除window函数的警告。
  3. 预测期数控制:通过h=10指定预测10个月,确保输出覆盖至1982年8月。
  4. 列名替换:将原Year列替换为Year/Month,完全匹配需求格式。

内容的提问来源于stack exchange,提问作者Daniel James

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 14:25:56