R语言tsibble下如何构建多维度分组自上而下预测模型
为更清晰说明问题,以下为编辑后的问题版本:
案例概述
现有一份归属不同国家、包含多个层级(line、main group、subgroup、product)的数据集,目标是基于自上而下(top down)方法构建聚合预测,找到适配场景的最优预测聚合层级。
目前已构建待聚合的tsibble对象,但使用aggregate_key()仅能构建单组父子层级关系(例如main group/product),需要覆盖所有层级关系才能筛选出最优聚合层级。
待确认问题
- 是否可以编写循环遍历所有可能层级,还是必须逐个单独运行各层级计算?
- 需要针对每个国家单独生成预测。虽然自下而上(bottom up)方法中可直接通过
aggregate_key(subgroup/product)*country构建分组结构,但该写法在自上而下预测中无法正常运行,是否可以实现该分组逻辑,还是必须逐个国家单独开展预测?
问题复现代码
dat <- data.frame(id=1:n, date=seq.Date(as.Date("2020-1-1"), as.Date("2020-1-20"), "day"), country = rep(LETTERS[1:2], n/2), line=sample(1:4,n, replace=TRUE), main_group=sample(1:5, n, replace=TRUE), subgroup=sample(1:10,n, replace=TRUE), product=sample(1:20), sales=sample(281:300)) dat_tsibble = dat %>% as_tsibble(key = c(product, country), index = date) dat_aggregated = dat_tsibble %>% aggregate_key((subgroup/product)*country, sales= sum(sales)) fit <- dat_aggregated %>% model(base = ETS(sales)) %>% reconcile( td = top_down(base) ) fc = fit %>% forecast(h="30 day")
说明:当前示例数据框无法生成有效预测,但运行后返回的报错信息与实际场景中的报错完全一致。
解答
多遍历层级的实现方案
不需要逐个手动运行各层级计算,可通过批量遍历的方式覆盖所有合法层级组合:
- 先枚举所有符合业务逻辑的层级嵌套公式,排除子父级倒挂的无效组合,例如4个产品维度可生成
line、line/main_group、line/main_group/subgroup、line/main_group/subgroup/product、main_group、main_group/subgroup等所有合法嵌套结构。 - 将聚合、建模、调和、预测、精度计算的全流程封装为自定义函数,输入为层级公式,输出为对应层级的预测精度指标(如RMSE、MASE)。
- 借助
purrr::map()或基础R的lapply()遍历所有枚举的层级公式,批量运行后对比精度结果,即可筛选出最优聚合层级。
分国家自上而下预测的报错解决方案
该报错核心原因是:aggregate_key()中使用*做交叉分组时,生成的结构包含跨国家聚合节点,而top_down()调和方法默认要求层级为单根节点的纯树状嵌套结构,交叉分组生成的多并行分组结构会导致调和时无法定位唯一顶层根节点,最终触发报错。
不需要逐个国家单独运行预测,推荐使用分组嵌套的方式实现:先按country字段做分组嵌套,再对每个国家的分组子集单独构建产品维度的层级聚合结构,保证每个国家内部是独立的单根嵌套层级,完全适配top_down()的方法要求,参考实现代码如下:
library(tidyverse) library(tsibble) library(fable) nested_dat <- dat %>% as_tsibble(key = c(product, country), index = date) %>% # 按国家分组嵌套 nest(data = -country) %>% mutate( # 单国家内做产品维度层级聚合 agg_data = map(data, ~.x %>% aggregate_key(subgroup/product, sales = sum(sales))), # 单国家内建模、自上而下调和 model_fit = map(agg_data, ~.x %>% model(base = ETS(sales)) %>% reconcile(td = top_down(base))), # 单国家生成预测 forecast_res = map(model_fit, ~.x %>% forecast(h = "30 day")) ) # 解压得到所有国家的最终预测结果 final_fc <- nested_dat %>% select(country, forecast_res) %>% unnest(forecast_res)
如果需要保留跨国别的聚合层级,无法直接使用默认top_down()方法,可手动指定顶层节点,或换用适配交叉分组结构的min_trace()方法做调和。
内容的提问来源于stack exchange,提问作者user19296910
相关产品推荐
相关产品推荐

