You need to enable JavaScript to run this app. R中聚合双时间序列应用双输入函数计算年度NRMSE的报错问题
优惠活动
大模型
产品
解决方案
定价
更多

R中聚合双时间序列应用双输入函数计算年度NRMSE的报错问题

报错根因

stats::aggregate.ts 处理多列ts矩阵输入时,会逐列拆分数据,单独将每个列的时间块传入FUN计算,不会把同时间块的多列数据打包成矩阵传给自定义函数。因此你写的nrmse_fun收到的输入永远是长度为365的一维向量,而非两列矩阵,对向量执行Yt_matrix[,1]的二维子集操作,自然会触发“维度数量不正确”的报错。

可落地的实现方案

你最初的NRMSE计算逻辑、自定义函数本身都没有问题,只需要匹配工具的运行逻辑调整实现路径,推荐两种可直接复用的写法:

方案1:拆分聚合项,完全适配aggregate原生逻辑(对新手最友好)

NRMSE的公式本身可以拆分为两个独立的单变量年度聚合计算,完全不需要双列联合传参,和你最初的计算结果完全等价:

# 替换为你实际使用的Yt和Yt1对象即可
Yt <- ts(rnorm(1825), frequency = 365, start = c(1, 1))
Yt1 <- ts(smooth(Yt), frequency = 365, start = c(1, 1))

# 构造逐天残差平方序列
resid_sq <- (Yt1 - Yt)^2

# 逐年度聚合两个单变量序列
rmse_per_year <- sqrt(aggregate(resid_sq, nfrequency = 1, FUN = mean, na.rm = TRUE))
orig_mean_per_year <- aggregate(Yt, nfrequency = 1, FUN = mean, na.rm = TRUE)

# 计算最终年度NRMSE,输出本身就是符合格式的ts对象
nrmse_per_year <- rmse_per_year / orig_mean_per_year

输出结果的结构和你预期完全一致:

Time Series:
Start = 1 
End = 5 
Frequency = 1 
[1] 数值1 数值2 数值3 数值4 数值5

方案2:保留原双列矩阵计算逻辑,绕开aggregate的传参限制

如果你不想改动原来的nrmse_fun,可以先生成年度分组标签,直接对矩阵做分组计算,最后转回ts对象:

# 你原来写好的NRMSE函数,完全不需要修改
nrmse_fun <- function(Yt_matrix) {
  sqrt(mean((Yt_matrix[,1] - Yt_matrix[,2])^2, na.rm=TRUE)) / mean(Yt_matrix[,2], na.rm=TRUE)
}

# 生成每个日度观测对应的年度分组标签
year_group <- time(Yt) %/% 1

# 对齐两个序列为双列数值矩阵
aligned_mat <- cbind(Yt1 = as.numeric(Yt1), Yt = as.numeric(Yt))

# 按分组调用原函数计算
nrmse_vals <- tapply(
  X = seq_len(nrow(aligned_mat)),
  INDEX = year_group,
  FUN = function(row_idx) nrmse_fun(aligned_mat[row_idx, ])
)

# 转回符合格式要求的ts对象
nrmse_per_year <- ts(nrmse_vals, start = 1, frequency = 1)

关于工具选择的说明

aggregate 本身并不适合跨变量的联合聚合场景——它的设计目标是逐列处理同结构的时间序列,硬要在它的FUN里写跨列逻辑必然会遇到传参不匹配的问题。上述两种方案都能实现你需要的按年输出5个NRMSE值、最终结果为ts对象的要求,其中方案1代码量最少,最适合R新手使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 02:24:02