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
相关产品推荐
相关产品推荐

