循环输出到列表。有没有优雅的选择?

Loop output to list. Is there an elegant alternative?

为了从具有许多模型和 ID 的长格式的预测输出与实际值中获取准确度值,我想遍历数据并使用 tail(input_object, -Forecast_horizon).

我宁愿使用一些简洁的方法来执行此操作,因为这样的循环看起来很奇怪而且很粗糙。

library(forecast)
library(tibble)
testing_frame <- tibble(.value = rep(c(11,32,35,57,67,34),12),
                            test_value = rep(c(12,33,40,60,69,44),12),
                        id = rep(as.factor(c(rep(1,6),rep(2,6),rep(3,6),rep(4,6),rep(5,6),rep(6,6))),2),
                        model = as.character(c(rep(1,36),c(rep(2,36)))))

H = 6
iter = c(1:12)
datalist = list()
i = 1

for (i in iter) {
    acc_all = forecast::accuracy(ts(head(testing_frame$.value,frequency = H),n=H),
                                 ts(head(testing_frame$test_value,frequency = H),n=H))
    testing_frame <- tail(testing_frame, -H)
    acc_all_out = acc_all[,7]
    datalist[[i]] <- acc_all_out 
}
output = do.call(rbind, datalist)

就 .value/test_value 而言,id/model 没有变化,因此每次迭代的输出都是相同的。但是,大概您的实际数据有这种变化。下面是一种按 id 和模型(即 12 组)分组的方法,然后使用 nest()map()unnest_wider() 来获得结果

testing_frame %>% group_by(id, model) %>% 
  nest() %>% 
  mutate(acc = map(data,~accuracy(ts(.x$.value, frequency = H),ts(.x$test_value,frequency=H)))) %>% 
  unnest_wider(acc) %>% 
  rename_all(~c("id","model", "data","ME","RMSE","MAE","MPE","MAPE","ACF1", "Theil's U"))

输出:

   id    model data                ME  RMSE   MAE   MPE  MAPE   ACF1 `Theil's U`
   <fct> <chr> <list>           <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>       <dbl>
 1 1     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 2 2     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 3 3     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 4 4     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 5 5     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 6 6     1     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 7 1     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 8 2     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
 9 3     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
10 4     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
11 5     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128
12 6     2     <tibble [6 x 2]>  3.67  4.83  3.67  9.08  9.08 -0.114       0.128

一种更简洁的方法是在 summarise()accuracy():

返回的每个指标创建新列
library(tidyverse)
library(forecast)

testing_frame %>% 
  group_by(id, model) %>% 
  summarise(
    accuracy(
      ts(.value, frequency = H),
      ts(test_value, frequency = H)
    ) %>% as_tibble()
  )
#> # A tibble: 12 x 9
#> # Groups:   id [6]
#>    id    model    ME  RMSE   MAE   MPE  MAPE   ACF1 `Theil's U`
#>    <fct> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>       <dbl>
#>  1 1     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  2 1     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  3 2     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  4 2     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  5 3     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  6 3     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  7 4     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  8 4     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#>  9 5     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#> 10 5     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#> 11 6     1      3.67  4.83  3.67  9.08  9.08 -0.114       0.128
#> 12 6     2      3.67  4.83  3.67  9.08  9.08 -0.114       0.128