PAYATHON 2026

如何用 fpp3 绘制包含多条预测分位数曲线的图?

数据阿明

可以先用 autoplot() 绘制预测结果,再用 geom_line() 叠加分位数曲线。将百分位数编号映射到 group,就能把不同预测季度中的同一百分位数连成曲线。

完整示例

这段代码适用于题目中的单序列、单模型预测:

library(fpp3)
library(distributional)

fc <- aus_production |>
  model(ARIMA(Beer)) |>
  forecast(h = 20)

pc <- seq_len(99)

qf <- fc |>
  as_tibble() |>
  group_by(Quarter) |>
  reframe(percentile = quantile(Beer, pc / 100)) |>
  unnest(percentile) |>
  group_by(Quarter) |>
  mutate(pc = row_number()) |>
  ungroup()

autoplot(fc, aus_production, level = 95) +
  geom_line(
    data = qf,
    mapping = aes(
      x = Quarter,
      y = percentile,
      group = pc,
      colour = factor(pc)
    ),
    inherit.aes = FALSE,
    linewidth = 0.35
  ) +
  scale_colour_manual(
    values = rainbow(length(pc)),
    guide = "none"
  ) +
  labs(
    x = "季度",
    y = "Beer"
  )

为什么要按 pc 分组?

展开后的 qf 中,每个预测季度都有 99 个分位数值。传入的概率依次为 0.01 到 0.99,因此可以在各季度内用 row_number() 为这些值标记对应的百分位数编号。

绘图时,各映射的作用是:

  • x = Quarter:保留预测结果中的季度时间索引。
  • y = percentile:将计算出的分位数值作为纵坐标。
  • group = pc:连接不同季度中相同百分位数的点。
  • colour = factor(pc):为每条分位数曲线分配一种颜色。

inherit.aes = FALSE 让该图层使用自己的映射,避免继承预测图中针对其他数据列的映射。

题目里的 rep(pc, 20) 也可用于当前结果,但它依赖预测期数和展开后的行顺序。按季度编号后,调整 forecast(h = ...) 时就不必同步修改这里的 20。

与第一段代码的区别

第一段代码先根据 95% 预测区间反推标准差,再用 qnorm() 按正态分布计算分位数,依赖正态分布假设。

在 fpp3 的预测结果中,Beer 列保存的是预测分布,可以直接调用 quantile(Beer, pc / 100) 提取分位数,无需从区间宽度重新推算标准差。

图中的 95% 预测区间由 autoplot() 绘制,99 条彩色曲线由额外的 geom_line() 图层绘制。每条曲线表示各预测季度的同一分位数,不代表一条模拟出来的未来样本路径。

如果以后同时预测多个序列或多个模型,计算分位数时需要保留相应的序列键和 .model。绘图时也要将它们纳入分组,或使用分面展示,避免连接不同序列的点。若所用 ggplot2 不支持 linewidth,可将该参数改为 size。

备注:内容仅供参考。