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

如何在R中计算滚动4个月误差率:误差求和除以同期真实值总和

月度库存预测滚动误差率计算

需求说明

  • 业务场景:预测公司未来9个月的库存采购商品数量,数据为月度维度
  • 计算目标:4个月周期的滚动误差率,计算逻辑为滚动窗口内预测值总和/对应窗口内实际销量总和衍生的误差率,可按需调整百分比系数
  • 窗口范围:依次计算第1-4月、2-5月直至6-9月的误差

问题说明

之前使用代码ma(me/outsamp*100, order = 4 , centre =FALSE)计算结果不符合预期,原因是该逻辑是对单月百分比误差取平均,和需求的「窗口总预测/总实际」的计算逻辑不一致。

示例数据

df<-data.frame(predictions = c(393.4, 511.4, 471.7, 679.2, 613.9, 
                           456.2, 603.2, 668.2, 512.4), 
           outsamp = c(662, 416, 594, 495, 442, 480, 263, 464, 507),
           ME = c(268.6, -95.4, 122.3, -184.2, -171.9, 23.8, -340.2, -204.2, -5.4),
           `error (4)` = c(NA, 0.0513613290263037, -0.169080636877247, -0.104425658876181, 0.400297619047619, -0.419951485748939, 
                          -0.306884480746791, NA, NA),
           `error (5)` = c(NA, NA, -0.0232272901494825,-0.125834363411619, -0.241952506596306, -0.408908582089552, -0.323701298701299, NA, NA), 
           `error (6)` = c(NA, NA, -0.0119132405309161, -0.24,-0.275529583637692, -0.332742361373067, NA, NA, NA))

实现代码

1. for循环实现

n <- nrow(df)
window_len <- 4
# 初始化结果列
df$calc_error_4 <- NA

for (i in 1:(n - window_len + 1)) {
  # 提取当前窗口的索引
  window_idx <- i:(i + window_len - 1)
  # 计算窗口内总预测、总实际
  total_pred <- sum(df$predictions[window_idx])
  total_actual <- sum(df$outsamp[window_idx])
  # 计算误差率,对齐到窗口的最后一个位置
  df$calc_error_4[max(window_idx)] <- (total_pred - total_actual) / total_actual
}

2. rollapply 简洁实现

library(zoo)
window_len <- 4

df$calc_error_4 <- rollapply(
  1:nrow(df),
  width = window_len,
  align = "right", # 结果对齐到窗口最后一行
  FUN = function(idx) {
    (sum(df$predictions[idx]) - sum(df$outsamp[idx])) / sum(df$outsamp[idx])
  },
  fill = NA # 不足窗口的位置填充NA
)

计算得到的calc_error_4和Excel导入的error (4)字段完全一致,符合需求。如果要计算5个月、6个月的滚动误差,只需修改window_len参数即可。

内容的提问来源于stack exchange,提问作者Christoffer Nielsen-jasa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 01:39:02