如何处理modeltime预测中melt及unmelt操作导致的变量丢失问题
问题原因
- 分组逻辑缺失:当前将240个变量融化后的长表直接作为输入训练单一Prophet模型,Modeltime的单序列模型默认不会自动区分
variable分组,相当于把所有变量的数值合并为单条时间序列训练,预测结果自然无法覆盖全部240个变量。 - 时间拆分逻辑错误:直接对全量长表执行
initial_time_split是按行顺序切割前80%为训练集,而非按每个变量单独按时间维度拆分训练/测试集,导致大量变量的2020年区间数据根本没有进入测试集,预测结果不存在这些变量的记录,宽表转换时就会丢失。 - 预测值列取值错误:
modeltime_forecast输出的预测值存储在.value字段,你之前提取的value是原始实际观测值,取值错误也会导致宽表转换异常。
修正方案
采用分组嵌套的方式对每个变量单独训练模型、预测,保证所有变量都有对应的预测结果,修正后代码如下:
suppressPackageStartupMessages(library(tidyverse)) suppressPackageStartupMessages(library(lubridate)) suppressPackageStartupMessages(library(tidymodels)) suppressPackageStartupMessages(library(modeltime)) ## 生成模拟数据 dates <- ymd("2016-01-01") + months(0:59) fake_values <- c(661,678,1094,1987,3310,2105,1452,983,1107,805,675,684,436,514,668,206,19,23,365,456,1174,1760,735,366, 510,580,939,1127,2397,1514,1370,832,765,661,497,328,566,631,983,1876,2784,2928,2543,1508,1175,8,1733, 862,779,1112,1446,2407,3917,2681,2397,1246,1125,1223,1234,1239, 661,678,1094,1987,3310,2105,1452,983,1107,805,675,684,436,514,668,206,19,23,365,456,1174,1760,735,366, 510,580,939,1127,2397,1514,1370,832,765,661,497,328,566,631,983,1876,2784,2928,2543,1508,1175,8,1733, 862,779,1112,1446,2407,3917,2681,2397,1246,1125,1223,1234,1239, 661,678,1094,1987,3310,2105,1452,983,1107,805,675,684,436,514,668,206,19,23,365,456,1174,1760,735,366, 510,580,939,1127,2397,1514,1370,832,765,661,497,328,566,631,983,1876,2784,2928,2543,1508,1175,8,1733, 862,779,1112,1446,2407,3917,2681,2397,1246,1125,1223,1234,1239, 661,678,1094,1987,3310,2105,1452,983,1107,805,675,684,436,514,668,206,19,23,365,456,1174,1760,735,366, 510,580,939,1127,2397,1514,1370,832,765,661,497,328,566,631,983,1876,2784,2928,2543,1508,1175,8,1733, 862,779,1112,1446,2407,3917,2681,2397,1246,1125,1223,1234,1239) replicate <- rep(1,60) %*% t.default(fake_values) replicate <- as.data.frame(replicate) df <- bind_cols(replicate, dates) %>% rename(dates = ...241) ## 转换为长表 data <- reshape2::melt(df, id.var='dates') ## 按变量分组嵌套,每个变量对应独立时间序列 data_nested <- data %>% group_by(variable) %>% nest() ## 定义单序列预测函数 forecast_single <- function(df) { # 分组内按时间拆分训练测试集 split_obj <- initial_time_split(df, prop = 0.8) # 训练Prophet模型 model_fit <- prophet_reg() %>% set_engine("prophet") %>% fit(value ~ dates, data = training(split_obj)) # 生成预测结果 modeltime_table(model_fit) %>% modeltime_forecast( new_data = testing(split_obj), actual_data = df, keep_data = TRUE ) %>% filter(str_detect(.key, "prediction")) } ## 批量对所有变量执行预测 fc_all <- data_nested %>% mutate(forecast_res = map(data, forecast_single)) %>% unnest(forecast_res) ## 筛选2020年数据并转换为宽表 fc_wide_prophet <- fc_all %>% filter(.index >= ymd("2020-01-01"), .index <= ymd("2020-12-01")) %>% select(.index, variable, .value) %>% pivot_wider(names_from = variable, values_from = .value)
内容的提问来源于stack exchange,提问作者LGe
相关产品推荐
相关产品推荐

