UPDATE: 2022-12-27 10:47:54

はじめに

tidymodelsパッケージの使い方をいくつかのノートに分けてまとめている。tidymodelsパッケージは、統計モデルや機械学習モデルを構築するために必要なパッケージをコレクションしているパッケージで、非常に色んなパッケージがある。ここでは、今回はmodeltimeパッケージで複数の時系列を予測する方法に加え、モデルをチューニングする方法についてまとめていく。モデルの数理的な側面や機械学習の用語などは、このノートでは扱わない。

下記の公式ドキュメントやtidymodelsパッケージに関する書籍を参考にしている。

modeltimeパッケージの目的

modeltimeパッケージは、時系列モデルの構築を効率よく行うためのパッケージで、tidymodelsパッケージと組み合わせて時系列モデルを作成する際に使用される。時系列予測のための体系的なワークフローを提供し、時系列ブーストモデルなど新しいアルゴリズムもカバーしている点が特徴的。

ここでは、複数の時系列データがある場合に効率よく予測モデルを構築する方法をまとめる。

特に下記のブログについて、サイトをなぞりながら、不明点を追記しながらまとめていく。非常に勉強になるブログなので、私のメモではなく、下記を見たほうが早いかも。

ここでの目的はベースラインモデルの作成方法やグローバルモデルのパラメタチューニング方法を学ぶことで、将来の予測をすることはここではしない。

データの紹介

まずは必要なパッケージやデータを読み込んでおく。これはスペインのカタルーニャの発電量のデータとのこと。

Sèrie temporal mensual de la producció elèctrica per tecnologies, demanda elèctrica en barres de central, consum elèctric per sectors, demanda de gas natural i consum de carburants d’automoció. 技術別の電力生産、中央バスバーの電力需要、部門別の電力消費、天然ガスの需要、自動車の燃料消費の月次時系列。

library(modeltime)
library(tidymodels)
library(tidyverse)
library(timetk)
library(lubridate)
library(DT)

tk_augment_anomaly_diagnostics <- function(df){
    nombres <- names(df)[2:length(df)]
    for(j in 1:length(nombres)){
        nombre <- nombres[j]
        nombre1 <- paste(nombre, "_anomaly", sep = "")
        df <- df %>%
                dplyr::bind_cols(df %>%
                            dplyr::select(date, {{nombre}}) %>%
                            purrr::set_names(c("date", "value")) %>%
                            tk_anomaly_diagnostics(.date_var = date, .value = value) %>%
                            dplyr::select(anomaly) %>%
                            dplyr::mutate(anomaly = if_else(anomaly == "No", 0, 1)) %>%
                            dplyr::rename({{nombre1}} := anomaly)
                          )
    }
    return(df)
}

URL <- "https://analisi.transparenciacatalunya.cat/api/views/j7xc-3kfh/rows.csv?accessType=DOWNLOAD"
df_raw <- read_csv(URL)
DT::datatable(df_raw)

FEEIが頭についているカラムを対象にする。また、日付関係のカラムのフォーマットを修正する必要があるので、少しばかり前処理を行ない、WIDE型のデータをLONG型のパネルデータに変形しておく。

df <- df_raw %>%
  dplyr::select(date = Data, starts_with("FEEI")) %>%
  dplyr::mutate(date = dmy(paste0("01/", date))) %>%
  dplyr::rename_with(.cols = starts_with("FEEI"),
              .fn   = ~ str_replace(., "FEEI_", "")) %>%
  # FEEIで数ヶ月分の欠損値があるので削除
  tidyr::drop_na(ConsObrPub) %>%
  tidyr::pivot_longer(-date, names_to = "id", values_to = "value") %>%
  dplyr::mutate(id = as.factor(id)) %>%
  tk_augment_anomaly_diagnostics() %>% 
  dplyr::select(date, id, value, anomaly = value_anomaly)

DT::datatable(df)

ここでは、13セクター?エリア?の時系列の予測を行なうことになる。単位は月次で、開始月は2005-01-01で、終了月は2021-01-01、レコード数は197個(およそ16年分)。

df %>%
  dplyr::group_by(id) %>%
  dplyr::summarise(
    n.obs = n(),
    start_date = min(date),
    end_date = max(date),
    min_value = min(value),
    mean_value = mean(value),
    max_value = max(value),
    mean_anomaly = round(mean(anomaly) * 100, 1)
  ) %>%
  print(n = 20)
## # A tibble: 13 × 8
##    id                n.obs start_date end_date   min_v…¹ mean_…² max_v…³ mean_…⁴
##    <fct>             <int> <date>     <date>       <dbl>   <dbl>   <dbl>   <dbl>
##  1 AlimBegudaTabac     197 2005-01-01 2021-05-01   131.    162.    206.     11.7
##  2 AltresIndus         197 2005-01-01 2021-05-01    97.6   152.    214.     24.9
##  3 AltresMatConstr     197 2005-01-01 2021-05-01    10.4    25.9    42.1     0  
##  4 CimentsCalGuix      197 2005-01-01 2021-05-01    13.7    41.4    75.4    14.2
##  5 ConsObrPub          197 2005-01-01 2021-05-01    16.2    25.4    46.1     0  
##  6 ConstrMedTrans      197 2005-01-01 2021-05-01    24.3    59.9   107       3  
##  7 IndusVidre          197 2005-01-01 2021-05-01    12.5    26.6    35       0  
##  8 Metalurgia          197 2005-01-01 2021-05-01     5.8    12.4    19.7     0  
##  9 PastaPaperCartro    197 2005-01-01 2021-05-01    62.5    78.6   113.      0  
## 10 QuimPetroquim       197 2005-01-01 2021-05-01   273.    385.    484.     59.4
## 11 RestaTransforMet…   197 2005-01-01 2021-05-01    64.8   108.    148.     13.7
## 12 SiderFoneria        197 2005-01-01 2021-05-01    52.7   135.    190.     13.7
## 13 TextilConfecCuir…   197 2005-01-01 2021-05-01    30.1    64.8   119.     16.2
## # … with abbreviated variable names ¹​min_value, ²​mean_value, ³​max_value,
## #   ⁴​mean_anomaly

13個の時系列を可視化しておく。QuimPetroquimは他に比べてボリュームが大きい。

plot_time_series(
  .data = df,
  .date_var = date,
  .value = value,
  .color_var = id,
  .smooth = FALSE,
  .interactive = FALSE
)

ベースモデルの作成

ベースモデルの作成を行う前に、データを分割する。テストデータは、各idの6か月間の発電量を予測することにする。

splits <- time_series_split(
    data = df,
    assess = 6,
    cumulative = TRUE
)

splits %>%
    tk_time_series_cv_plan() %>%
    plot_time_series_cv_plan(
      date, 
      value,
      .interactive = FALSE)

参照しているブログに従い、window_regモデルとnaive_regモデルをベースモデルとして利用する。

window_regモデルはウインドサイズに従って計算することでモデルを作成し、naive_regモデルは最後の観測値を系列の次の値として利用することでモデルを作成する。これらのモデルに対して、レシピを作成する。

これらのパラメタ違いのモデルの効率の良い使い方がわからなかったのだが、ブログではカスタムグリッドを定義して、ベースラインモデルとして構築しており、すごく勉強になる。

モデルは合計12個作成されているが、これは設定しているウインドウサイズの違いや、季節周期の違いによるもの(ブログでは24モデルあるが、ここでは12個)。

window_grid_median_tbl <- tibble(window_size = seq(2,12,2)) %>%
  create_model_grid(
    f_model_spec  = window_reg,
    id            = "id",
    engine_name   = "window_function",
    engine_params = list(window_function = ~ median(.))
  )

snaive_grid_tbl <- tibble(seasonal_period = seq(9, 24, 3)) %>%
  create_model_grid(f_model_spec  = naive_reg,
                    id            = "id",
                    engine_name   = "snaive")

models <- union(
  snaive_grid_tbl %>% dplyr::select(.models), 
  window_grid_median_tbl %>% dplyr::select(.models)
  )

list(
  models %>% pluck(".models", 1),
  models %>% pluck(".models", 6)
)
## [[1]]
## Naive Forecast Model Specification (regression)
## 
## Main Arguments:
##   id = id
##   seasonal_period = 9
## 
## Computational engine: snaive 
## 
## 
## [[2]]
## Naive Forecast Model Specification (regression)
## 
## Main Arguments:
##   id = id
##   seasonal_period = 24
## 
## Computational engine: snaive

モデルを2つのレシピと掛け合わせてワークフローセットオブジェクトを作成する。

recipe_basic <- recipe(value ~ date + id, data = training(splits))

# recipe_basic_features <- recipe(value ~ id + date, data = training(splits)) %>%
#     step_timeseries_signature(date) %>%
#     step_rm(matches("(xts$)|(iso$)|(^.pm)")) %>%
#     step_zv(all_predictors()) %>%
#     step_dummy(all_nominal_predictors())

recipe_outliers <- recipe(value ~ ., data = training(splits))

# recipe_outliers_features <- recipe(value ~ ., data = training(splits)) %>%
#     step_timeseries_signature(date) %>%
#     step_rm(matches("(xts$)|(iso$)|(^.pm)")) %>%
#     step_zv(all_predictors()) %>%
#     step_dummy(all_nominal_predictors())

モデルが12個、レシピが2個なので、合計24モデルを計算する。

workflowset <- workflow_set(
    preproc = list(
        recipe_basic,
        recipe_outliers
    ),
    models = models$.models,
    cross  = TRUE
)
workflowset
## # A workflow set/tibble: 24 × 4
##    wflow_id               info             option    result    
##    <chr>                  <list>           <list>    <list>    
##  1 recipe_1_naive_reg_1   <tibble [1 × 4]> <opts[0]> <list [0]>
##  2 recipe_1_naive_reg_2   <tibble [1 × 4]> <opts[0]> <list [0]>
##  3 recipe_1_naive_reg_3   <tibble [1 × 4]> <opts[0]> <list [0]>
##  4 recipe_1_naive_reg_4   <tibble [1 × 4]> <opts[0]> <list [0]>
##  5 recipe_1_naive_reg_5   <tibble [1 × 4]> <opts[0]> <list [0]>
##  6 recipe_1_naive_reg_6   <tibble [1 × 4]> <opts[0]> <list [0]>
##  7 recipe_1_window_reg_7  <tibble [1 × 4]> <opts[0]> <list [0]>
##  8 recipe_1_window_reg_8  <tibble [1 × 4]> <opts[0]> <list [0]>
##  9 recipe_1_window_reg_9  <tibble [1 × 4]> <opts[0]> <list [0]>
## 10 recipe_1_window_reg_10 <tibble [1 × 4]> <opts[0]> <list [0]>
## # … with 14 more rows

modeltime_fit_workflowset関数は、複数の時系列に対して、順次または並行して各モデルをフィットさせるfit関数のラッパー関数。フィッティングした後はモデルテーブルにmodeltime_table関数で登録する必要があるが、この関数では一気通貫でモデルの登録まで行える。実行時間を短縮するために、並列処理を実行する。

# detectCores()
# [1] 8
parallel_start(8)

modeltime_baseline_fit <- workflowset %>%
    modeltime_fit_workflowset(
        data    = training(splits),
        control = control_fit_workflowset(
            verbose   = TRUE,
            allow_par = TRUE
        )
    )

parallel_stop()

合計24個のモデルが登録されていることがわかる。

modeltime_baseline_fit
## # Modeltime Table
## # A tibble: 24 × 3
##    .model_id .model     .model_desc           
##        <int> <list>     <chr>                 
##  1         1 <workflow> RECIPE_1_NAIVE_REG_1  
##  2         2 <workflow> RECIPE_1_NAIVE_REG_2  
##  3         3 <workflow> RECIPE_1_NAIVE_REG_3  
##  4         4 <workflow> RECIPE_1_NAIVE_REG_4  
##  5         5 <workflow> RECIPE_1_NAIVE_REG_5  
##  6         6 <workflow> RECIPE_1_NAIVE_REG_6  
##  7         7 <workflow> RECIPE_1_WINDOW_REG_7 
##  8         8 <workflow> RECIPE_1_WINDOW_REG_8 
##  9         9 <workflow> RECIPE_1_WINDOW_REG_9 
## 10        10 <workflow> RECIPE_1_WINDOW_REG_10
## # … with 14 more rows

このモデルテーブルを利用して、テストデータのキャリブレーションを行なう。ちょっとここらへんから複雑になってくるので、メモがてら細かくまとめておく。

キャリブレーションを行なうと、モデル24個、セクター13個、予測月が6ヶ月分の予測が.calibration_dataカラムに記録される。つまり、24 * 13 * 6 = 1872レコードが生成される。

modeltime_baseline_fit_tmp1 <- modeltime_baseline_fit %>%
  modeltime_calibrate(testing(splits), id = "id")

map_dfr(.x = 1:nrow(modeltime_baseline_fit_tmp1),
        .f = function(x){modeltime_baseline_fit_tmp1 %>% pluck(".calibration_data", x)}) %>% 
  summarise(cnt = n())
## # A tibble: 1 × 1
##     cnt
##   <int>
## 1  1872

ここから更にmodeltime_accuracy関数を利用すると、312レコードが生成されているが、これはモデル24個で、13セクターの6ヶ月分の予測値を集計して評価したため、サイズが小さくなる。AlimBegudaTabacだけで24個の評価指標を持っている状態。

modeltime_baseline_fit_tmp2 <- modeltime_baseline_fit_tmp1 %>%
  modeltime_accuracy(acc_by_id = TRUE) # ローカルモデル精度

modeltime_baseline_fit_tmp2 %>% 
  dplyr::filter(id == "AlimBegudaTabac") %>% 
  print(n = 30)
## # A tibble: 24 × 10
##    .model_id .model_desc      .type id      mae  mape  mase smape  rmse      rsq
##        <int> <chr>            <chr> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
##  1         1 RECIPE_1_NAIVE_… Test  Alim… 12.1   7.16 1.01   7.10 14.5   7.06e-4
##  2         2 RECIPE_1_NAIVE_… Test  Alim…  4.93  2.96 0.415  2.97  5.51  6.20e-1
##  3         3 RECIPE_1_NAIVE_… Test  Alim… 19.3  11.4  1.63  11.2  21.1   1.70e-1
##  4         4 RECIPE_1_NAIVE_… Test  Alim… 18.4  11.3  1.55  10.4  22.5   1.06e-2
##  5         5 RECIPE_1_NAIVE_… Test  Alim… 13.4   8.06 1.13   7.64 16.7   1.34e-2
##  6         6 RECIPE_1_NAIVE_… Test  Alim…  6.43  3.84 0.542  3.92  7.66  3.98e-1
##  7         7 RECIPE_1_WINDOW… Test  Alim… 28.2  17.1  2.38  15.6  29.4  NA      
##  8         8 RECIPE_1_WINDOW… Test  Alim… 25.4  15.4  2.14  14.2  26.7  NA      
##  9         9 RECIPE_1_WINDOW… Test  Alim… 19.3  11.7  1.62  11.0  20.9  NA      
## 10        10 RECIPE_1_WINDOW… Test  Alim… 14.7   8.98 1.24   8.52 16.2  NA      
## 11        11 RECIPE_1_WINDOW… Test  Alim…  8.78  5.28 0.739  5.18  9.62 NA      
## 12        12 RECIPE_1_WINDOW… Test  Alim…  7.2   4.26 0.606  4.25  8.30 NA      
## 13        13 RECIPE_2_NAIVE_… Test  Alim… 12.1   7.16 1.01   7.10 14.5   7.06e-4
## 14        14 RECIPE_2_NAIVE_… Test  Alim…  4.93  2.96 0.415  2.97  5.51  6.20e-1
## 15        15 RECIPE_2_NAIVE_… Test  Alim… 19.3  11.4  1.63  11.2  21.1   1.70e-1
## 16        16 RECIPE_2_NAIVE_… Test  Alim… 18.4  11.3  1.55  10.4  22.5   1.06e-2
## 17        17 RECIPE_2_NAIVE_… Test  Alim… 13.4   8.06 1.13   7.64 16.7   1.34e-2
## 18        18 RECIPE_2_NAIVE_… Test  Alim…  6.43  3.84 0.542  3.92  7.66  3.98e-1
## 19        19 RECIPE_2_WINDOW… Test  Alim… 28.2  17.1  2.38  15.6  29.4  NA      
## 20        20 RECIPE_2_WINDOW… Test  Alim… 25.4  15.4  2.14  14.2  26.7  NA      
## 21        21 RECIPE_2_WINDOW… Test  Alim… 19.3  11.7  1.62  11.0  20.9  NA      
## 22        22 RECIPE_2_WINDOW… Test  Alim… 14.7   8.98 1.24   8.52 16.2  NA      
## 23        23 RECIPE_2_WINDOW… Test  Alim…  8.78  5.28 0.739  5.18  9.62 NA      
## 24        24 RECIPE_2_WINDOW… Test  Alim…  7.2   4.26 0.606  4.25  8.30 NA

ここから各セクターに最適なモデルを選択していく。頭が混乱するので、順をおって確認すると、先程と同じ手順をもう一度行なうが、まずはキャリブレーションを行って、予測値を算出し、集約して評価指標を計算する。

# modeltime_baseline_fitは24個のモデルが登録されているモデルテーブル
modeltime_baseline_fit_caliration <- modeltime_baseline_fit %>%
  modeltime_calibrate(testing(splits), id = "id") %>%
  modeltime_accuracy(acc_by_id = TRUE)

そして、モデルごとではなく、セクター(id)ごとに最適なモデルを見つけるため、slice_min関数で抜き出す。このあたりの段階を説明するために、AlimBegudaTabacセクターに絞って挙動を確認する。

先程も確認したとおり、AlimBegudaTabacセクターの予測は24個のモデルで行われているため、24レコードある。

modeltime_baseline_fit_caliration %>% 
  dplyr::filter(id == "AlimBegudaTabac") %>% 
  print(n = 30)
## # A tibble: 24 × 10
##    .model_id .model_desc      .type id      mae  mape  mase smape  rmse      rsq
##        <int> <chr>            <chr> <fct> <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
##  1         1 RECIPE_1_NAIVE_… Test  Alim… 12.1   7.16 1.01   7.10 14.5   7.06e-4
##  2         2 RECIPE_1_NAIVE_… Test  Alim…  4.93  2.96 0.415  2.97  5.51  6.20e-1
##  3         3 RECIPE_1_NAIVE_… Test  Alim… 19.3  11.4  1.63  11.2  21.1   1.70e-1
##  4         4 RECIPE_1_NAIVE_… Test  Alim… 18.4  11.3  1.55  10.4  22.5   1.06e-2
##  5         5 RECIPE_1_NAIVE_… Test  Alim… 13.4   8.06 1.13   7.64 16.7   1.34e-2
##  6         6 RECIPE_1_NAIVE_… Test  Alim…  6.43  3.84 0.542  3.92  7.66  3.98e-1
##  7         7 RECIPE_1_WINDOW… Test  Alim… 28.2  17.1  2.38  15.6  29.4  NA      
##  8         8 RECIPE_1_WINDOW… Test  Alim… 25.4  15.4  2.14  14.2  26.7  NA      
##  9         9 RECIPE_1_WINDOW… Test  Alim… 19.3  11.7  1.62  11.0  20.9  NA      
## 10        10 RECIPE_1_WINDOW… Test  Alim… 14.7   8.98 1.24   8.52 16.2  NA      
## 11        11 RECIPE_1_WINDOW… Test  Alim…  8.78  5.28 0.739  5.18  9.62 NA      
## 12        12 RECIPE_1_WINDOW… Test  Alim…  7.2   4.26 0.606  4.25  8.30 NA      
## 13        13 RECIPE_2_NAIVE_… Test  Alim… 12.1   7.16 1.01   7.10 14.5   7.06e-4
## 14        14 RECIPE_2_NAIVE_… Test  Alim…  4.93  2.96 0.415  2.97  5.51  6.20e-1
## 15        15 RECIPE_2_NAIVE_… Test  Alim… 19.3  11.4  1.63  11.2  21.1   1.70e-1
## 16        16 RECIPE_2_NAIVE_… Test  Alim… 18.4  11.3  1.55  10.4  22.5   1.06e-2
## 17        17 RECIPE_2_NAIVE_… Test  Alim… 13.4   8.06 1.13   7.64 16.7   1.34e-2
## 18        18 RECIPE_2_NAIVE_… Test  Alim…  6.43  3.84 0.542  3.92  7.66  3.98e-1
## 19        19 RECIPE_2_WINDOW… Test  Alim… 28.2  17.1  2.38  15.6  29.4  NA      
## 20        20 RECIPE_2_WINDOW… Test  Alim… 25.4  15.4  2.14  14.2  26.7  NA      
## 21        21 RECIPE_2_WINDOW… Test  Alim… 19.3  11.7  1.62  11.0  20.9  NA      
## 22        22 RECIPE_2_WINDOW… Test  Alim… 14.7   8.98 1.24   8.52 16.2  NA      
## 23        23 RECIPE_2_WINDOW… Test  Alim…  8.78  5.28 0.739  5.18  9.62 NA      
## 24        24 RECIPE_2_WINDOW… Test  Alim…  7.2   4.26 0.606  4.25  8.30 NA

ここから、slice_min関数をrmse基準で利用するとrmseカラムが最小のレコードがスライスして取り出される。最小が複数該当する場合は、複数行取り出されるので注意。

modeltime_baseline_fit_caliration %>% 
  filter(id == "AlimBegudaTabac") %>% 
  slice_min(rmse) 
## # A tibble: 2 × 10
##   .model_id .model_desc          .type id      mae  mape  mase smape  rmse   rsq
##       <int> <chr>                <chr> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1         2 RECIPE_1_NAIVE_REG_2 Test  Alim…  4.93  2.96 0.415  2.97  5.51 0.620
## 2        14 RECIPE_2_NAIVE_REG_2 Test  Alim…  4.93  2.96 0.415  2.97  5.51 0.620

これらは予測精度が同じなので、どちらを利用しても同じなので、.model_idが小さい方をさらに取得する。

modeltime_baseline_fit_caliration %>% 
  filter(id == "AlimBegudaTabac") %>% 
  slice_min(rmse) %>% 
  slice_min(.model_id)
## # A tibble: 1 × 10
##   .model_id .model_desc          .type id      mae  mape  mase smape  rmse   rsq
##       <int> <chr>                <chr> <fct> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1         2 RECIPE_1_NAIVE_REG_2 Test  Alim…  4.93  2.96 0.415  2.97  5.51 0.620

このようにすることで、各セクターに対して最適なモデルが13個取り出される。

baseline_models <- modeltime_baseline_fit_caliration %>%
  group_by(id) %>% 
  slice_min(rmse) %>%
  slice_min(.model_id) %>%
  ungroup()

baseline_models
## # A tibble: 13 × 10
##    .model_id .model_desc      .type id       mae  mape  mase smape   rmse    rsq
##        <int> <chr>            <chr> <fct>  <dbl> <dbl> <dbl> <dbl>  <dbl>  <dbl>
##  1         2 RECIPE_1_NAIVE_… Test  Alim…  4.93   2.96 0.415  2.97  5.51   0.620
##  2        11 RECIPE_1_WINDOW… Test  Altr…  7.78   6.58 0.563  6.33 10.2   NA    
##  3        12 RECIPE_1_WINDOW… Test  Altr…  1.42   7.19 0.681  7.08  1.64  NA    
##  4         8 RECIPE_1_WINDOW… Test  Cime…  2.7    8.38 0.659  8.35  3.13  NA    
##  5         9 RECIPE_1_WINDOW… Test  Cons…  1.38   5.91 0.505  5.81  1.76  NA    
##  6         9 RECIPE_1_WINDOW… Test  Cons…  3.4    5.74 0.496  5.74  4.46  NA    
##  7         9 RECIPE_1_WINDOW… Test  Indu…  2.15   9.48 0.597  9.64  2.64  NA    
##  8         7 RECIPE_1_WINDOW… Test  Meta…  0.717  6.58 0.535  6.33  0.993 NA    
##  9         2 RECIPE_1_NAIVE_… Test  Past…  3.10   3.99 0.876  4.06  3.52   0.680
## 10        12 RECIPE_1_WINDOW… Test  Quim… 21.7    6.78 0.568  6.65 26.7   NA    
## 11        11 RECIPE_1_WINDOW… Test  Rest…  7.43   7.43 0.831  7.43  8.00  NA    
## 12         7 RECIPE_1_WINDOW… Test  Side…  5.82   4.56 0.752  4.62  6.99  NA    
## 13         7 RECIPE_1_WINDOW… Test  Text…  2.85   5.81 0.594  5.86  3.71  NA

24個のモデルが登録されているモデルテーブルmodeltime_baseline_fit、各13セクターに対するモデルが登録されているテーブルbaseline_modelsを使って、必要なモデルだけが記録されたモデルテーブルを作成する。インナージョインでフィルタリングする。このときに、セクターごとにモデルが同じケースもあるが、必要なモデル13個に絞られる。

# modeltime_baseline_fitは24個のモデルが登録されているモデルテーブル
# baseline_modelsは各13セクターに対するモデルが登録されているテーブル

modeltime_baseline_fit %>%
  dplyr::inner_join(baseline_models, by = ".model_id") %>%
  dplyr::select(.model_id, .model, .model_desc.x, id) %>%
  dplyr::rename(.model_desc = .model_desc.x)
## # Modeltime Table
## # A tibble: 13 × 4
##    .model_id .model     .model_desc            id                    
##        <int> <list>     <chr>                  <fct>                 
##  1         2 <workflow> RECIPE_1_NAIVE_REG_2   AlimBegudaTabac       
##  2         2 <workflow> RECIPE_1_NAIVE_REG_2   PastaPaperCartro      
##  3         7 <workflow> RECIPE_1_WINDOW_REG_7  Metalurgia            
##  4         7 <workflow> RECIPE_1_WINDOW_REG_7  SiderFoneria          
##  5         7 <workflow> RECIPE_1_WINDOW_REG_7  TextilConfecCuirCalçat
##  6         8 <workflow> RECIPE_1_WINDOW_REG_8  CimentsCalGuix        
##  7         9 <workflow> RECIPE_1_WINDOW_REG_9  ConsObrPub            
##  8         9 <workflow> RECIPE_1_WINDOW_REG_9  ConstrMedTrans        
##  9         9 <workflow> RECIPE_1_WINDOW_REG_9  IndusVidre            
## 10        11 <workflow> RECIPE_1_WINDOW_REG_11 AltresIndus           
## 11        11 <workflow> RECIPE_1_WINDOW_REG_11 RestaTransforMetal    
## 12        12 <workflow> RECIPE_1_WINDOW_REG_12 AltresMatConstr       
## 13        12 <workflow> RECIPE_1_WINDOW_REG_12 QuimPetroquim

このとき、モデルテーブルにidという名前でカラムを残すとエラーになるので削除したモデルテーブルを作成する。他の名前であれば問題ないが、キャリブレーションすると削除されるっぽい。

modeltime_baseline_tbl <- modeltime_baseline_fit %>% 
                            dplyr::inner_join(baseline_models, by = ".model_id") %>% 
                            dplyr::select(.model_id, .model, .model_desc.x) %>% 
                            dplyr::rename(.model_desc = .model_desc.x)
modeltime_baseline_tbl
## # Modeltime Table
## # A tibble: 13 × 3
##    .model_id .model     .model_desc           
##        <int> <list>     <chr>                 
##  1         2 <workflow> RECIPE_1_NAIVE_REG_2  
##  2         2 <workflow> RECIPE_1_NAIVE_REG_2  
##  3         7 <workflow> RECIPE_1_WINDOW_REG_7 
##  4         7 <workflow> RECIPE_1_WINDOW_REG_7 
##  5         7 <workflow> RECIPE_1_WINDOW_REG_7 
##  6         8 <workflow> RECIPE_1_WINDOW_REG_8 
##  7         9 <workflow> RECIPE_1_WINDOW_REG_9 
##  8         9 <workflow> RECIPE_1_WINDOW_REG_9 
##  9         9 <workflow> RECIPE_1_WINDOW_REG_9 
## 10        11 <workflow> RECIPE_1_WINDOW_REG_11
## 11        11 <workflow> RECIPE_1_WINDOW_REG_11
## 12        12 <workflow> RECIPE_1_WINDOW_REG_12
## 13        12 <workflow> RECIPE_1_WINDOW_REG_12

実質的に各セクターidに対して必要なモデルが紐付いた状態なので、ここからテストデータを使って予測する。ただ、予測すると1つの問題が発生する。1つのセクターに対して、先程取り出したモデル全ての予測値が計算されてしまう。

data_forecasted <- modeltime_baseline_tbl %>%
                    # modeltime_calibrateはconfを計算するために必要
                    modeltime_calibrate(testing(splits), id = "id") %>%
                    modeltime_forecast(
                      new_data = testing(splits),
                      actual_data = training(splits),
                      conf_by_id = TRUE,
                      keep_data = TRUE
                    )

data_forecasted %>% 
  dplyr::filter(id == "ConsObrPub") %>% 
  print(n = 300)
## # A tibble: 269 × 11
##     .model_id .model_…¹ .key  .index     .value .conf…² .conf…³ date       id   
##         <int> <chr>     <fct> <date>      <dbl>   <dbl>   <dbl> <date>     <fct>
##   1        NA ACTUAL    actu… 2005-01-01   24.1    NA      NA   2005-01-01 Cons…
##   2        NA ACTUAL    actu… 2005-02-01   25.8    NA      NA   2005-02-01 Cons…
##   3        NA ACTUAL    actu… 2005-03-01   27.8    NA      NA   2005-03-01 Cons…
##   4        NA ACTUAL    actu… 2005-04-01   25.1    NA      NA   2005-04-01 Cons…
##   5        NA ACTUAL    actu… 2005-05-01   24      NA      NA   2005-05-01 Cons…
##   6        NA ACTUAL    actu… 2005-06-01   21.5    NA      NA   2005-06-01 Cons…
##   7        NA ACTUAL    actu… 2005-07-01   23.7    NA      NA   2005-07-01 Cons…
##   8        NA ACTUAL    actu… 2005-08-01   25.1    NA      NA   2005-08-01 Cons…
##   9        NA ACTUAL    actu… 2005-09-01   21.9    NA      NA   2005-09-01 Cons…
##  10        NA ACTUAL    actu… 2005-10-01   22.7    NA      NA   2005-10-01 Cons…
##  11        NA ACTUAL    actu… 2005-11-01   22.9    NA      NA   2005-11-01 Cons…
##  12        NA ACTUAL    actu… 2005-12-01   24.5    NA      NA   2005-12-01 Cons…
##  13        NA ACTUAL    actu… 2006-01-01   27.8    NA      NA   2006-01-01 Cons…
##  14        NA ACTUAL    actu… 2006-02-01   27.9    NA      NA   2006-02-01 Cons…
##  15        NA ACTUAL    actu… 2006-03-01   30.5    NA      NA   2006-03-01 Cons…
##  16        NA ACTUAL    actu… 2006-04-01   27.6    NA      NA   2006-04-01 Cons…
##  17        NA ACTUAL    actu… 2006-05-01   24.4    NA      NA   2006-05-01 Cons…
##  18        NA ACTUAL    actu… 2006-06-01   23.7    NA      NA   2006-06-01 Cons…
##  19        NA ACTUAL    actu… 2006-07-01   22.6    NA      NA   2006-07-01 Cons…
##  20        NA ACTUAL    actu… 2006-08-01   24.8    NA      NA   2006-08-01 Cons…
##  21        NA ACTUAL    actu… 2006-09-01   22.4    NA      NA   2006-09-01 Cons…
##  22        NA ACTUAL    actu… 2006-10-01   26.4    NA      NA   2006-10-01 Cons…
##  23        NA ACTUAL    actu… 2006-11-01   28.9    NA      NA   2006-11-01 Cons…
##  24        NA ACTUAL    actu… 2006-12-01   24.2    NA      NA   2006-12-01 Cons…
##  25        NA ACTUAL    actu… 2007-01-01   29.1    NA      NA   2007-01-01 Cons…
##  26        NA ACTUAL    actu… 2007-02-01   27.9    NA      NA   2007-02-01 Cons…
##  27        NA ACTUAL    actu… 2007-03-01   41.4    NA      NA   2007-03-01 Cons…
##  28        NA ACTUAL    actu… 2007-04-01   30.1    NA      NA   2007-04-01 Cons…
##  29        NA ACTUAL    actu… 2007-05-01   27.1    NA      NA   2007-05-01 Cons…
##  30        NA ACTUAL    actu… 2007-06-01   24.1    NA      NA   2007-06-01 Cons…
##  31        NA ACTUAL    actu… 2007-07-01   25.7    NA      NA   2007-07-01 Cons…
##  32        NA ACTUAL    actu… 2007-08-01   24      NA      NA   2007-08-01 Cons…
##  33        NA ACTUAL    actu… 2007-09-01   24.7    NA      NA   2007-09-01 Cons…
##  34        NA ACTUAL    actu… 2007-10-01   25.1    NA      NA   2007-10-01 Cons…
##  35        NA ACTUAL    actu… 2007-11-01   28.7    NA      NA   2007-11-01 Cons…
##  36        NA ACTUAL    actu… 2007-12-01   27.6    NA      NA   2007-12-01 Cons…
##  37        NA ACTUAL    actu… 2008-01-01   32      NA      NA   2008-01-01 Cons…
##  38        NA ACTUAL    actu… 2008-02-01   35.1    NA      NA   2008-02-01 Cons…
##  39        NA ACTUAL    actu… 2008-03-01   33.5    NA      NA   2008-03-01 Cons…
##  40        NA ACTUAL    actu… 2008-04-01   32.9    NA      NA   2008-04-01 Cons…
##  41        NA ACTUAL    actu… 2008-05-01   32      NA      NA   2008-05-01 Cons…
##  42        NA ACTUAL    actu… 2008-06-01   27.8    NA      NA   2008-06-01 Cons…
##  43        NA ACTUAL    actu… 2008-07-01   26.3    NA      NA   2008-07-01 Cons…
##  44        NA ACTUAL    actu… 2008-08-01   30.4    NA      NA   2008-08-01 Cons…
##  45        NA ACTUAL    actu… 2008-09-01   26.8    NA      NA   2008-09-01 Cons…
##  46        NA ACTUAL    actu… 2008-10-01   31.4    NA      NA   2008-10-01 Cons…
##  47        NA ACTUAL    actu… 2008-11-01   32.9    NA      NA   2008-11-01 Cons…
##  48        NA ACTUAL    actu… 2008-12-01   30      NA      NA   2008-12-01 Cons…
##  49        NA ACTUAL    actu… 2009-01-01   39.7    NA      NA   2009-01-01 Cons…
##  50        NA ACTUAL    actu… 2009-02-01   46.1    NA      NA   2009-02-01 Cons…
##  51        NA ACTUAL    actu… 2009-03-01   40.4    NA      NA   2009-03-01 Cons…
##  52        NA ACTUAL    actu… 2009-04-01   39.9    NA      NA   2009-04-01 Cons…
##  53        NA ACTUAL    actu… 2009-05-01   34.1    NA      NA   2009-05-01 Cons…
##  54        NA ACTUAL    actu… 2009-06-01   34.3    NA      NA   2009-06-01 Cons…
##  55        NA ACTUAL    actu… 2009-07-01   29.3    NA      NA   2009-07-01 Cons…
##  56        NA ACTUAL    actu… 2009-08-01   27.7    NA      NA   2009-08-01 Cons…
##  57        NA ACTUAL    actu… 2009-09-01   32.6    NA      NA   2009-09-01 Cons…
##  58        NA ACTUAL    actu… 2009-10-01   36.6    NA      NA   2009-10-01 Cons…
##  59        NA ACTUAL    actu… 2009-11-01   40      NA      NA   2009-11-01 Cons…
##  60        NA ACTUAL    actu… 2009-12-01   39.7    NA      NA   2009-12-01 Cons…
##  61        NA ACTUAL    actu… 2010-01-01   38.1    NA      NA   2010-01-01 Cons…
##  62        NA ACTUAL    actu… 2010-02-01   35.3    NA      NA   2010-02-01 Cons…
##  63        NA ACTUAL    actu… 2010-03-01   39.1    NA      NA   2010-03-01 Cons…
##  64        NA ACTUAL    actu… 2010-04-01   37      NA      NA   2010-04-01 Cons…
##  65        NA ACTUAL    actu… 2010-05-01   33      NA      NA   2010-05-01 Cons…
##  66        NA ACTUAL    actu… 2010-06-01   37.3    NA      NA   2010-06-01 Cons…
##  67        NA ACTUAL    actu… 2010-07-01   35.6    NA      NA   2010-07-01 Cons…
##  68        NA ACTUAL    actu… 2010-08-01   37.5    NA      NA   2010-08-01 Cons…
##  69        NA ACTUAL    actu… 2010-09-01   34.5    NA      NA   2010-09-01 Cons…
##  70        NA ACTUAL    actu… 2010-10-01   31.8    NA      NA   2010-10-01 Cons…
##  71        NA ACTUAL    actu… 2010-11-01   34.5    NA      NA   2010-11-01 Cons…
##  72        NA ACTUAL    actu… 2010-12-01   35.5    NA      NA   2010-12-01 Cons…
##  73        NA ACTUAL    actu… 2011-01-01   36.2    NA      NA   2011-01-01 Cons…
##  74        NA ACTUAL    actu… 2011-02-01   34.9    NA      NA   2011-02-01 Cons…
##  75        NA ACTUAL    actu… 2011-03-01   36.3    NA      NA   2011-03-01 Cons…
##  76        NA ACTUAL    actu… 2011-04-01   33.6    NA      NA   2011-04-01 Cons…
##  77        NA ACTUAL    actu… 2011-05-01   26.5    NA      NA   2011-05-01 Cons…
##  78        NA ACTUAL    actu… 2011-06-01   31.7    NA      NA   2011-06-01 Cons…
##  79        NA ACTUAL    actu… 2011-07-01   31      NA      NA   2011-07-01 Cons…
##  80        NA ACTUAL    actu… 2011-08-01   32.6    NA      NA   2011-08-01 Cons…
##  81        NA ACTUAL    actu… 2011-09-01   28.3    NA      NA   2011-09-01 Cons…
##  82        NA ACTUAL    actu… 2011-10-01   28.3    NA      NA   2011-10-01 Cons…
##  83        NA ACTUAL    actu… 2011-11-01   27.7    NA      NA   2011-11-01 Cons…
##  84        NA ACTUAL    actu… 2011-12-01   26.6    NA      NA   2011-12-01 Cons…
##  85        NA ACTUAL    actu… 2012-01-01   26.9    NA      NA   2012-01-01 Cons…
##  86        NA ACTUAL    actu… 2012-02-01   28.9    NA      NA   2012-02-01 Cons…
##  87        NA ACTUAL    actu… 2012-03-01   27.5    NA      NA   2012-03-01 Cons…
##  88        NA ACTUAL    actu… 2012-04-01   24.5    NA      NA   2012-04-01 Cons…
##  89        NA ACTUAL    actu… 2012-05-01   23.4    NA      NA   2012-05-01 Cons…
##  90        NA ACTUAL    actu… 2012-06-01   23.3    NA      NA   2012-06-01 Cons…
##  91        NA ACTUAL    actu… 2012-07-01   24.6    NA      NA   2012-07-01 Cons…
##  92        NA ACTUAL    actu… 2012-08-01   23.5    NA      NA   2012-08-01 Cons…
##  93        NA ACTUAL    actu… 2012-09-01   25.8    NA      NA   2012-09-01 Cons…
##  94        NA ACTUAL    actu… 2012-10-01   22.4    NA      NA   2012-10-01 Cons…
##  95        NA ACTUAL    actu… 2012-11-01   24.9    NA      NA   2012-11-01 Cons…
##  96        NA ACTUAL    actu… 2012-12-01   23.1    NA      NA   2012-12-01 Cons…
##  97        NA ACTUAL    actu… 2013-01-01   22.9    NA      NA   2013-01-01 Cons…
##  98        NA ACTUAL    actu… 2013-02-01   24.6    NA      NA   2013-02-01 Cons…
##  99        NA ACTUAL    actu… 2013-03-01   21.3    NA      NA   2013-03-01 Cons…
## 100        NA ACTUAL    actu… 2013-04-01   20.6    NA      NA   2013-04-01 Cons…
## 101        NA ACTUAL    actu… 2013-05-01   19.3    NA      NA   2013-05-01 Cons…
## 102        NA ACTUAL    actu… 2013-06-01   19.8    NA      NA   2013-06-01 Cons…
## 103        NA ACTUAL    actu… 2013-07-01   19.7    NA      NA   2013-07-01 Cons…
## 104        NA ACTUAL    actu… 2013-08-01   23.4    NA      NA   2013-08-01 Cons…
## 105        NA ACTUAL    actu… 2013-09-01   22      NA      NA   2013-09-01 Cons…
## 106        NA ACTUAL    actu… 2013-10-01   21.2    NA      NA   2013-10-01 Cons…
## 107        NA ACTUAL    actu… 2013-11-01   21      NA      NA   2013-11-01 Cons…
## 108        NA ACTUAL    actu… 2013-12-01   20.1    NA      NA   2013-12-01 Cons…
## 109        NA ACTUAL    actu… 2014-01-01   21.2    NA      NA   2014-01-01 Cons…
## 110        NA ACTUAL    actu… 2014-02-01   21.1    NA      NA   2014-02-01 Cons…
## 111        NA ACTUAL    actu… 2014-03-01   19.9    NA      NA   2014-03-01 Cons…
## 112        NA ACTUAL    actu… 2014-04-01   19      NA      NA   2014-04-01 Cons…
## 113        NA ACTUAL    actu… 2014-05-01   18      NA      NA   2014-05-01 Cons…
## 114        NA ACTUAL    actu… 2014-06-01   16.9    NA      NA   2014-06-01 Cons…
## 115        NA ACTUAL    actu… 2014-07-01   19.2    NA      NA   2014-07-01 Cons…
## 116        NA ACTUAL    actu… 2014-08-01   20.7    NA      NA   2014-08-01 Cons…
## 117        NA ACTUAL    actu… 2014-09-01   18.9    NA      NA   2014-09-01 Cons…
## 118        NA ACTUAL    actu… 2014-10-01   19.8    NA      NA   2014-10-01 Cons…
## 119        NA ACTUAL    actu… 2014-11-01   19.3    NA      NA   2014-11-01 Cons…
## 120        NA ACTUAL    actu… 2014-12-01   18.5    NA      NA   2014-12-01 Cons…
## 121        NA ACTUAL    actu… 2015-01-01   19.9    NA      NA   2015-01-01 Cons…
## 122        NA ACTUAL    actu… 2015-02-01   20.6    NA      NA   2015-02-01 Cons…
## 123        NA ACTUAL    actu… 2015-03-01   19.3    NA      NA   2015-03-01 Cons…
## 124        NA ACTUAL    actu… 2015-04-01   19.6    NA      NA   2015-04-01 Cons…
## 125        NA ACTUAL    actu… 2015-05-01   17.5    NA      NA   2015-05-01 Cons…
## 126        NA ACTUAL    actu… 2015-06-01   17.8    NA      NA   2015-06-01 Cons…
## 127        NA ACTUAL    actu… 2015-07-01   20.7    NA      NA   2015-07-01 Cons…
## 128        NA ACTUAL    actu… 2015-08-01   22.6    NA      NA   2015-08-01 Cons…
## 129        NA ACTUAL    actu… 2015-09-01   19.1    NA      NA   2015-09-01 Cons…
## 130        NA ACTUAL    actu… 2015-10-01   18.7    NA      NA   2015-10-01 Cons…
## 131        NA ACTUAL    actu… 2015-11-01   18.4    NA      NA   2015-11-01 Cons…
## 132        NA ACTUAL    actu… 2015-12-01   18.8    NA      NA   2015-12-01 Cons…
## 133        NA ACTUAL    actu… 2016-01-01   19.2    NA      NA   2016-01-01 Cons…
## 134        NA ACTUAL    actu… 2016-02-01   19.1    NA      NA   2016-02-01 Cons…
## 135        NA ACTUAL    actu… 2016-03-01   18.9    NA      NA   2016-03-01 Cons…
## 136        NA ACTUAL    actu… 2016-04-01   19.1    NA      NA   2016-04-01 Cons…
## 137        NA ACTUAL    actu… 2016-05-01   17.6    NA      NA   2016-05-01 Cons…
## 138        NA ACTUAL    actu… 2016-06-01   17.4    NA      NA   2016-06-01 Cons…
## 139        NA ACTUAL    actu… 2016-07-01   19.5    NA      NA   2016-07-01 Cons…
## 140        NA ACTUAL    actu… 2016-08-01   21.7    NA      NA   2016-08-01 Cons…
## 141        NA ACTUAL    actu… 2016-09-01   20      NA      NA   2016-09-01 Cons…
## 142        NA ACTUAL    actu… 2016-10-01   22.2    NA      NA   2016-10-01 Cons…
## 143        NA ACTUAL    actu… 2016-11-01   19.7    NA      NA   2016-11-01 Cons…
## 144        NA ACTUAL    actu… 2016-12-01   19.9    NA      NA   2016-12-01 Cons…
## 145        NA ACTUAL    actu… 2017-01-01   21      NA      NA   2017-01-01 Cons…
## 146        NA ACTUAL    actu… 2017-02-01   21.8    NA      NA   2017-02-01 Cons…
## 147        NA ACTUAL    actu… 2017-03-01   19.7    NA      NA   2017-03-01 Cons…
## 148        NA ACTUAL    actu… 2017-04-01   19.8    NA      NA   2017-04-01 Cons…
## 149        NA ACTUAL    actu… 2017-05-01   18.4    NA      NA   2017-05-01 Cons…
## 150        NA ACTUAL    actu… 2017-06-01   20.2    NA      NA   2017-06-01 Cons…
## 151        NA ACTUAL    actu… 2017-07-01   22      NA      NA   2017-07-01 Cons…
## 152        NA ACTUAL    actu… 2017-08-01   24.1    NA      NA   2017-08-01 Cons…
## 153        NA ACTUAL    actu… 2017-09-01   21.1    NA      NA   2017-09-01 Cons…
## 154        NA ACTUAL    actu… 2017-10-01   20.5    NA      NA   2017-10-01 Cons…
## 155        NA ACTUAL    actu… 2017-11-01   21.3    NA      NA   2017-11-01 Cons…
## 156        NA ACTUAL    actu… 2017-12-01   21.4    NA      NA   2017-12-01 Cons…
## 157        NA ACTUAL    actu… 2018-01-01   22      NA      NA   2018-01-01 Cons…
## 158        NA ACTUAL    actu… 2018-02-01   20.8    NA      NA   2018-02-01 Cons…
## 159        NA ACTUAL    actu… 2018-03-01   26.7    NA      NA   2018-03-01 Cons…
## 160        NA ACTUAL    actu… 2018-04-01   24.2    NA      NA   2018-04-01 Cons…
## 161        NA ACTUAL    actu… 2018-05-01   21.4    NA      NA   2018-05-01 Cons…
## 162        NA ACTUAL    actu… 2018-06-01   21.6    NA      NA   2018-06-01 Cons…
## 163        NA ACTUAL    actu… 2018-07-01   21.7    NA      NA   2018-07-01 Cons…
## 164        NA ACTUAL    actu… 2018-08-01   29.7    NA      NA   2018-08-01 Cons…
## 165        NA ACTUAL    actu… 2018-09-01   24.4    NA      NA   2018-09-01 Cons…
## 166        NA ACTUAL    actu… 2018-10-01   19.4    NA      NA   2018-10-01 Cons…
## 167        NA ACTUAL    actu… 2018-11-01   27.1    NA      NA   2018-11-01 Cons…
## 168        NA ACTUAL    actu… 2018-12-01   24.6    NA      NA   2018-12-01 Cons…
## 169        NA ACTUAL    actu… 2019-01-01   23.6    NA      NA   2019-01-01 Cons…
## 170        NA ACTUAL    actu… 2019-02-01   26.9    NA      NA   2019-02-01 Cons…
## 171        NA ACTUAL    actu… 2019-03-01   20.6    NA      NA   2019-03-01 Cons…
## 172        NA ACTUAL    actu… 2019-04-01   22.7    NA      NA   2019-04-01 Cons…
## 173        NA ACTUAL    actu… 2019-05-01   21      NA      NA   2019-05-01 Cons…
## 174        NA ACTUAL    actu… 2019-06-01   21.3    NA      NA   2019-06-01 Cons…
## 175        NA ACTUAL    actu… 2019-07-01   23.1    NA      NA   2019-07-01 Cons…
## 176        NA ACTUAL    actu… 2019-08-01   27.2    NA      NA   2019-08-01 Cons…
## 177        NA ACTUAL    actu… 2019-09-01   25.5    NA      NA   2019-09-01 Cons…
## 178        NA ACTUAL    actu… 2019-10-01   23      NA      NA   2019-10-01 Cons…
## 179        NA ACTUAL    actu… 2019-11-01   24.5    NA      NA   2019-11-01 Cons…
## 180        NA ACTUAL    actu… 2019-12-01   22.2    NA      NA   2019-12-01 Cons…
## 181        NA ACTUAL    actu… 2020-01-01   23.6    NA      NA   2020-01-01 Cons…
## 182        NA ACTUAL    actu… 2020-02-01   24.2    NA      NA   2020-02-01 Cons…
## 183        NA ACTUAL    actu… 2020-03-01   23.2    NA      NA   2020-03-01 Cons…
## 184        NA ACTUAL    actu… 2020-04-01   19.8    NA      NA   2020-04-01 Cons…
## 185        NA ACTUAL    actu… 2020-05-01   18.8    NA      NA   2020-05-01 Cons…
## 186        NA ACTUAL    actu… 2020-06-01   16.2    NA      NA   2020-06-01 Cons…
## 187        NA ACTUAL    actu… 2020-07-01   24.5    NA      NA   2020-07-01 Cons…
## 188        NA ACTUAL    actu… 2020-08-01   26      NA      NA   2020-08-01 Cons…
## 189        NA ACTUAL    actu… 2020-09-01   26      NA      NA   2020-09-01 Cons…
## 190        NA ACTUAL    actu… 2020-10-01   23.6    NA      NA   2020-10-01 Cons…
## 191        NA ACTUAL    actu… 2020-11-01   21.9    NA      NA   2020-11-01 Cons…
## 192         2 RECIPE_1… pred… 2020-12-01   22.2    15.9    28.5 2020-12-01 Cons…
## 193         2 RECIPE_1… pred… 2021-01-01   23.6    17.3    29.9 2021-01-01 Cons…
## 194         2 RECIPE_1… pred… 2021-02-01   24.2    17.9    30.5 2021-02-01 Cons…
## 195         2 RECIPE_1… pred… 2021-03-01   23.2    16.9    29.5 2021-03-01 Cons…
## 196         2 RECIPE_1… pred… 2021-04-01   19.8    13.5    26.1 2021-04-01 Cons…
## 197         2 RECIPE_1… pred… 2021-05-01   18.8    12.5    25.1 2021-05-01 Cons…
## 198         2 RECIPE_1… pred… 2020-12-01   22.2    15.9    28.5 2020-12-01 Cons…
## 199         2 RECIPE_1… pred… 2021-01-01   23.6    17.3    29.9 2021-01-01 Cons…
## 200         2 RECIPE_1… pred… 2021-02-01   24.2    17.9    30.5 2021-02-01 Cons…
## 201         2 RECIPE_1… pred… 2021-03-01   23.2    16.9    29.5 2021-03-01 Cons…
## 202         2 RECIPE_1… pred… 2021-04-01   19.8    13.5    26.1 2021-04-01 Cons…
## 203         2 RECIPE_1… pred… 2021-05-01   18.8    12.5    25.1 2021-05-01 Cons…
## 204         7 RECIPE_1… pred… 2020-12-01   22.8    18.6    26.9 2020-12-01 Cons…
## 205         7 RECIPE_1… pred… 2021-01-01   22.8    18.6    26.9 2021-01-01 Cons…
## 206         7 RECIPE_1… pred… 2021-02-01   22.8    18.6    26.9 2021-02-01 Cons…
## 207         7 RECIPE_1… pred… 2021-03-01   22.8    18.6    26.9 2021-03-01 Cons…
## 208         7 RECIPE_1… pred… 2021-04-01   22.8    18.6    26.9 2021-04-01 Cons…
## 209         7 RECIPE_1… pred… 2021-05-01   22.8    18.6    26.9 2021-05-01 Cons…
## 210         7 RECIPE_1… pred… 2020-12-01   22.8    18.6    26.9 2020-12-01 Cons…
## 211         7 RECIPE_1… pred… 2021-01-01   22.8    18.6    26.9 2021-01-01 Cons…
## 212         7 RECIPE_1… pred… 2021-02-01   22.8    18.6    26.9 2021-02-01 Cons…
## 213         7 RECIPE_1… pred… 2021-03-01   22.8    18.6    26.9 2021-03-01 Cons…
## 214         7 RECIPE_1… pred… 2021-04-01   22.8    18.6    26.9 2021-04-01 Cons…
## 215         7 RECIPE_1… pred… 2021-05-01   22.8    18.6    26.9 2021-05-01 Cons…
## 216         7 RECIPE_1… pred… 2020-12-01   22.8    18.6    26.9 2020-12-01 Cons…
## 217         7 RECIPE_1… pred… 2021-01-01   22.8    18.6    26.9 2021-01-01 Cons…
## 218         7 RECIPE_1… pred… 2021-02-01   22.8    18.6    26.9 2021-02-01 Cons…
## 219         7 RECIPE_1… pred… 2021-03-01   22.8    18.6    26.9 2021-03-01 Cons…
## 220         7 RECIPE_1… pred… 2021-04-01   22.8    18.6    26.9 2021-04-01 Cons…
## 221         7 RECIPE_1… pred… 2021-05-01   22.8    18.6    26.9 2021-05-01 Cons…
## 222         8 RECIPE_1… pred… 2020-12-01   24.8    20.8    28.8 2020-12-01 Cons…
## 223         8 RECIPE_1… pred… 2021-01-01   24.8    20.8    28.8 2021-01-01 Cons…
## 224         8 RECIPE_1… pred… 2021-02-01   24.8    20.8    28.8 2021-02-01 Cons…
## 225         8 RECIPE_1… pred… 2021-03-01   24.8    20.8    28.8 2021-03-01 Cons…
## 226         8 RECIPE_1… pred… 2021-04-01   24.8    20.8    28.8 2021-04-01 Cons…
## 227         8 RECIPE_1… pred… 2021-05-01   24.8    20.8    28.8 2021-05-01 Cons…
## 228         9 RECIPE_1… pred… 2020-12-01   24.0    20.5    27.6 2020-12-01 Cons…
## 229         9 RECIPE_1… pred… 2021-01-01   24.0    20.5    27.6 2021-01-01 Cons…
## 230         9 RECIPE_1… pred… 2021-02-01   24.0    20.5    27.6 2021-02-01 Cons…
## 231         9 RECIPE_1… pred… 2021-03-01   24.0    20.5    27.6 2021-03-01 Cons…
## 232         9 RECIPE_1… pred… 2021-04-01   24.0    20.5    27.6 2021-04-01 Cons…
## 233         9 RECIPE_1… pred… 2021-05-01   24.0    20.5    27.6 2021-05-01 Cons…
## 234         9 RECIPE_1… pred… 2020-12-01   24.0    20.5    27.6 2020-12-01 Cons…
## 235         9 RECIPE_1… pred… 2021-01-01   24.0    20.5    27.6 2021-01-01 Cons…
## 236         9 RECIPE_1… pred… 2021-02-01   24.0    20.5    27.6 2021-02-01 Cons…
## 237         9 RECIPE_1… pred… 2021-03-01   24.0    20.5    27.6 2021-03-01 Cons…
## 238         9 RECIPE_1… pred… 2021-04-01   24.0    20.5    27.6 2021-04-01 Cons…
## 239         9 RECIPE_1… pred… 2021-05-01   24.0    20.5    27.6 2021-05-01 Cons…
## 240         9 RECIPE_1… pred… 2020-12-01   24.0    20.5    27.6 2020-12-01 Cons…
## 241         9 RECIPE_1… pred… 2021-01-01   24.0    20.5    27.6 2021-01-01 Cons…
## 242         9 RECIPE_1… pred… 2021-02-01   24.0    20.5    27.6 2021-02-01 Cons…
## 243         9 RECIPE_1… pred… 2021-03-01   24.0    20.5    27.6 2021-03-01 Cons…
## 244         9 RECIPE_1… pred… 2021-04-01   24.0    20.5    27.6 2021-04-01 Cons…
## 245         9 RECIPE_1… pred… 2021-05-01   24.0    20.5    27.6 2021-05-01 Cons…
## 246        11 RECIPE_1… pred… 2020-12-01   23.4    19.7    27.1 2020-12-01 Cons…
## 247        11 RECIPE_1… pred… 2021-01-01   23.4    19.7    27.1 2021-01-01 Cons…
## 248        11 RECIPE_1… pred… 2021-02-01   23.4    19.7    27.1 2021-02-01 Cons…
## 249        11 RECIPE_1… pred… 2021-03-01   23.4    19.7    27.1 2021-03-01 Cons…
## 250        11 RECIPE_1… pred… 2021-04-01   23.4    19.7    27.1 2021-04-01 Cons…
## 251        11 RECIPE_1… pred… 2021-05-01   23.4    19.7    27.1 2021-05-01 Cons…
## 252        11 RECIPE_1… pred… 2020-12-01   23.4    19.7    27.1 2020-12-01 Cons…
## 253        11 RECIPE_1… pred… 2021-01-01   23.4    19.7    27.1 2021-01-01 Cons…
## 254        11 RECIPE_1… pred… 2021-02-01   23.4    19.7    27.1 2021-02-01 Cons…
## 255        11 RECIPE_1… pred… 2021-03-01   23.4    19.7    27.1 2021-03-01 Cons…
## 256        11 RECIPE_1… pred… 2021-04-01   23.4    19.7    27.1 2021-04-01 Cons…
## 257        11 RECIPE_1… pred… 2021-05-01   23.4    19.7    27.1 2021-05-01 Cons…
## 258        12 RECIPE_1… pred… 2020-12-01   23.4    19.7    27.1 2020-12-01 Cons…
## 259        12 RECIPE_1… pred… 2021-01-01   23.4    19.7    27.1 2021-01-01 Cons…
## 260        12 RECIPE_1… pred… 2021-02-01   23.4    19.7    27.1 2021-02-01 Cons…
## 261        12 RECIPE_1… pred… 2021-03-01   23.4    19.7    27.1 2021-03-01 Cons…
## 262        12 RECIPE_1… pred… 2021-04-01   23.4    19.7    27.1 2021-04-01 Cons…
## 263        12 RECIPE_1… pred… 2021-05-01   23.4    19.7    27.1 2021-05-01 Cons…
## 264        12 RECIPE_1… pred… 2020-12-01   23.4    19.7    27.1 2020-12-01 Cons…
## 265        12 RECIPE_1… pred… 2021-01-01   23.4    19.7    27.1 2021-01-01 Cons…
## 266        12 RECIPE_1… pred… 2021-02-01   23.4    19.7    27.1 2021-02-01 Cons…
## 267        12 RECIPE_1… pred… 2021-03-01   23.4    19.7    27.1 2021-03-01 Cons…
## 268        12 RECIPE_1… pred… 2021-04-01   23.4    19.7    27.1 2021-04-01 Cons…
## 269        12 RECIPE_1… pred… 2021-05-01   23.4    19.7    27.1 2021-05-01 Cons…
## # … with 2 more variables: value <dbl>, anomaly <dbl>, and abbreviated variable
## #   names ¹​.model_desc, ²​.conf_lo, ³​.conf_hi

セクターConsObrPubが必要なモデルはRECIPE_1_WINDOW_REG_9である。他のセクターも同様なので、予測値と観測値を分割して、必要モデルの予測値をbaseline_modelsテーブルの情報を利用して限定する。

final_baseline_models <- data_forecasted %>%
  dplyr::filter(.key == "actual") %>%
  union(
    data_forecasted %>%
      dplyr::filter(.key == "prediction") %>%
      dplyr::inner_join(baseline_models, by = c("id", ".model_id")) %>%
      dplyr::select(.model_id, .model_desc.x, .key, .index, .value, 
                    .conf_lo, .conf_hi, date, id, value, anomaly) %>%
      dplyr::rename(.model_desc = .model_desc.x)
  )

final_baseline_models %>% 
  dplyr::filter(id == "ConsObrPub") %>% 
  print(n = 300)
## # A tibble: 197 × 11
##     .model_id .model_…¹ .key  .index     .value .conf…² .conf…³ date       id   
##         <int> <chr>     <fct> <date>      <dbl>   <dbl>   <dbl> <date>     <fct>
##   1        NA ACTUAL    actu… 2005-01-01   24.1    NA      NA   2005-01-01 Cons…
##   2        NA ACTUAL    actu… 2005-02-01   25.8    NA      NA   2005-02-01 Cons…
##   3        NA ACTUAL    actu… 2005-03-01   27.8    NA      NA   2005-03-01 Cons…
##   4        NA ACTUAL    actu… 2005-04-01   25.1    NA      NA   2005-04-01 Cons…
##   5        NA ACTUAL    actu… 2005-05-01   24      NA      NA   2005-05-01 Cons…
##   6        NA ACTUAL    actu… 2005-06-01   21.5    NA      NA   2005-06-01 Cons…
##   7        NA ACTUAL    actu… 2005-07-01   23.7    NA      NA   2005-07-01 Cons…
##   8        NA ACTUAL    actu… 2005-08-01   25.1    NA      NA   2005-08-01 Cons…
##   9        NA ACTUAL    actu… 2005-09-01   21.9    NA      NA   2005-09-01 Cons…
##  10        NA ACTUAL    actu… 2005-10-01   22.7    NA      NA   2005-10-01 Cons…
##  11        NA ACTUAL    actu… 2005-11-01   22.9    NA      NA   2005-11-01 Cons…
##  12        NA ACTUAL    actu… 2005-12-01   24.5    NA      NA   2005-12-01 Cons…
##  13        NA ACTUAL    actu… 2006-01-01   27.8    NA      NA   2006-01-01 Cons…
##  14        NA ACTUAL    actu… 2006-02-01   27.9    NA      NA   2006-02-01 Cons…
##  15        NA ACTUAL    actu… 2006-03-01   30.5    NA      NA   2006-03-01 Cons…
##  16        NA ACTUAL    actu… 2006-04-01   27.6    NA      NA   2006-04-01 Cons…
##  17        NA ACTUAL    actu… 2006-05-01   24.4    NA      NA   2006-05-01 Cons…
##  18        NA ACTUAL    actu… 2006-06-01   23.7    NA      NA   2006-06-01 Cons…
##  19        NA ACTUAL    actu… 2006-07-01   22.6    NA      NA   2006-07-01 Cons…
##  20        NA ACTUAL    actu… 2006-08-01   24.8    NA      NA   2006-08-01 Cons…
##  21        NA ACTUAL    actu… 2006-09-01   22.4    NA      NA   2006-09-01 Cons…
##  22        NA ACTUAL    actu… 2006-10-01   26.4    NA      NA   2006-10-01 Cons…
##  23        NA ACTUAL    actu… 2006-11-01   28.9    NA      NA   2006-11-01 Cons…
##  24        NA ACTUAL    actu… 2006-12-01   24.2    NA      NA   2006-12-01 Cons…
##  25        NA ACTUAL    actu… 2007-01-01   29.1    NA      NA   2007-01-01 Cons…
##  26        NA ACTUAL    actu… 2007-02-01   27.9    NA      NA   2007-02-01 Cons…
##  27        NA ACTUAL    actu… 2007-03-01   41.4    NA      NA   2007-03-01 Cons…
##  28        NA ACTUAL    actu… 2007-04-01   30.1    NA      NA   2007-04-01 Cons…
##  29        NA ACTUAL    actu… 2007-05-01   27.1    NA      NA   2007-05-01 Cons…
##  30        NA ACTUAL    actu… 2007-06-01   24.1    NA      NA   2007-06-01 Cons…
##  31        NA ACTUAL    actu… 2007-07-01   25.7    NA      NA   2007-07-01 Cons…
##  32        NA ACTUAL    actu… 2007-08-01   24      NA      NA   2007-08-01 Cons…
##  33        NA ACTUAL    actu… 2007-09-01   24.7    NA      NA   2007-09-01 Cons…
##  34        NA ACTUAL    actu… 2007-10-01   25.1    NA      NA   2007-10-01 Cons…
##  35        NA ACTUAL    actu… 2007-11-01   28.7    NA      NA   2007-11-01 Cons…
##  36        NA ACTUAL    actu… 2007-12-01   27.6    NA      NA   2007-12-01 Cons…
##  37        NA ACTUAL    actu… 2008-01-01   32      NA      NA   2008-01-01 Cons…
##  38        NA ACTUAL    actu… 2008-02-01   35.1    NA      NA   2008-02-01 Cons…
##  39        NA ACTUAL    actu… 2008-03-01   33.5    NA      NA   2008-03-01 Cons…
##  40        NA ACTUAL    actu… 2008-04-01   32.9    NA      NA   2008-04-01 Cons…
##  41        NA ACTUAL    actu… 2008-05-01   32      NA      NA   2008-05-01 Cons…
##  42        NA ACTUAL    actu… 2008-06-01   27.8    NA      NA   2008-06-01 Cons…
##  43        NA ACTUAL    actu… 2008-07-01   26.3    NA      NA   2008-07-01 Cons…
##  44        NA ACTUAL    actu… 2008-08-01   30.4    NA      NA   2008-08-01 Cons…
##  45        NA ACTUAL    actu… 2008-09-01   26.8    NA      NA   2008-09-01 Cons…
##  46        NA ACTUAL    actu… 2008-10-01   31.4    NA      NA   2008-10-01 Cons…
##  47        NA ACTUAL    actu… 2008-11-01   32.9    NA      NA   2008-11-01 Cons…
##  48        NA ACTUAL    actu… 2008-12-01   30      NA      NA   2008-12-01 Cons…
##  49        NA ACTUAL    actu… 2009-01-01   39.7    NA      NA   2009-01-01 Cons…
##  50        NA ACTUAL    actu… 2009-02-01   46.1    NA      NA   2009-02-01 Cons…
##  51        NA ACTUAL    actu… 2009-03-01   40.4    NA      NA   2009-03-01 Cons…
##  52        NA ACTUAL    actu… 2009-04-01   39.9    NA      NA   2009-04-01 Cons…
##  53        NA ACTUAL    actu… 2009-05-01   34.1    NA      NA   2009-05-01 Cons…
##  54        NA ACTUAL    actu… 2009-06-01   34.3    NA      NA   2009-06-01 Cons…
##  55        NA ACTUAL    actu… 2009-07-01   29.3    NA      NA   2009-07-01 Cons…
##  56        NA ACTUAL    actu… 2009-08-01   27.7    NA      NA   2009-08-01 Cons…
##  57        NA ACTUAL    actu… 2009-09-01   32.6    NA      NA   2009-09-01 Cons…
##  58        NA ACTUAL    actu… 2009-10-01   36.6    NA      NA   2009-10-01 Cons…
##  59        NA ACTUAL    actu… 2009-11-01   40      NA      NA   2009-11-01 Cons…
##  60        NA ACTUAL    actu… 2009-12-01   39.7    NA      NA   2009-12-01 Cons…
##  61        NA ACTUAL    actu… 2010-01-01   38.1    NA      NA   2010-01-01 Cons…
##  62        NA ACTUAL    actu… 2010-02-01   35.3    NA      NA   2010-02-01 Cons…
##  63        NA ACTUAL    actu… 2010-03-01   39.1    NA      NA   2010-03-01 Cons…
##  64        NA ACTUAL    actu… 2010-04-01   37      NA      NA   2010-04-01 Cons…
##  65        NA ACTUAL    actu… 2010-05-01   33      NA      NA   2010-05-01 Cons…
##  66        NA ACTUAL    actu… 2010-06-01   37.3    NA      NA   2010-06-01 Cons…
##  67        NA ACTUAL    actu… 2010-07-01   35.6    NA      NA   2010-07-01 Cons…
##  68        NA ACTUAL    actu… 2010-08-01   37.5    NA      NA   2010-08-01 Cons…
##  69        NA ACTUAL    actu… 2010-09-01   34.5    NA      NA   2010-09-01 Cons…
##  70        NA ACTUAL    actu… 2010-10-01   31.8    NA      NA   2010-10-01 Cons…
##  71        NA ACTUAL    actu… 2010-11-01   34.5    NA      NA   2010-11-01 Cons…
##  72        NA ACTUAL    actu… 2010-12-01   35.5    NA      NA   2010-12-01 Cons…
##  73        NA ACTUAL    actu… 2011-01-01   36.2    NA      NA   2011-01-01 Cons…
##  74        NA ACTUAL    actu… 2011-02-01   34.9    NA      NA   2011-02-01 Cons…
##  75        NA ACTUAL    actu… 2011-03-01   36.3    NA      NA   2011-03-01 Cons…
##  76        NA ACTUAL    actu… 2011-04-01   33.6    NA      NA   2011-04-01 Cons…
##  77        NA ACTUAL    actu… 2011-05-01   26.5    NA      NA   2011-05-01 Cons…
##  78        NA ACTUAL    actu… 2011-06-01   31.7    NA      NA   2011-06-01 Cons…
##  79        NA ACTUAL    actu… 2011-07-01   31      NA      NA   2011-07-01 Cons…
##  80        NA ACTUAL    actu… 2011-08-01   32.6    NA      NA   2011-08-01 Cons…
##  81        NA ACTUAL    actu… 2011-09-01   28.3    NA      NA   2011-09-01 Cons…
##  82        NA ACTUAL    actu… 2011-10-01   28.3    NA      NA   2011-10-01 Cons…
##  83        NA ACTUAL    actu… 2011-11-01   27.7    NA      NA   2011-11-01 Cons…
##  84        NA ACTUAL    actu… 2011-12-01   26.6    NA      NA   2011-12-01 Cons…
##  85        NA ACTUAL    actu… 2012-01-01   26.9    NA      NA   2012-01-01 Cons…
##  86        NA ACTUAL    actu… 2012-02-01   28.9    NA      NA   2012-02-01 Cons…
##  87        NA ACTUAL    actu… 2012-03-01   27.5    NA      NA   2012-03-01 Cons…
##  88        NA ACTUAL    actu… 2012-04-01   24.5    NA      NA   2012-04-01 Cons…
##  89        NA ACTUAL    actu… 2012-05-01   23.4    NA      NA   2012-05-01 Cons…
##  90        NA ACTUAL    actu… 2012-06-01   23.3    NA      NA   2012-06-01 Cons…
##  91        NA ACTUAL    actu… 2012-07-01   24.6    NA      NA   2012-07-01 Cons…
##  92        NA ACTUAL    actu… 2012-08-01   23.5    NA      NA   2012-08-01 Cons…
##  93        NA ACTUAL    actu… 2012-09-01   25.8    NA      NA   2012-09-01 Cons…
##  94        NA ACTUAL    actu… 2012-10-01   22.4    NA      NA   2012-10-01 Cons…
##  95        NA ACTUAL    actu… 2012-11-01   24.9    NA      NA   2012-11-01 Cons…
##  96        NA ACTUAL    actu… 2012-12-01   23.1    NA      NA   2012-12-01 Cons…
##  97        NA ACTUAL    actu… 2013-01-01   22.9    NA      NA   2013-01-01 Cons…
##  98        NA ACTUAL    actu… 2013-02-01   24.6    NA      NA   2013-02-01 Cons…
##  99        NA ACTUAL    actu… 2013-03-01   21.3    NA      NA   2013-03-01 Cons…
## 100        NA ACTUAL    actu… 2013-04-01   20.6    NA      NA   2013-04-01 Cons…
## 101        NA ACTUAL    actu… 2013-05-01   19.3    NA      NA   2013-05-01 Cons…
## 102        NA ACTUAL    actu… 2013-06-01   19.8    NA      NA   2013-06-01 Cons…
## 103        NA ACTUAL    actu… 2013-07-01   19.7    NA      NA   2013-07-01 Cons…
## 104        NA ACTUAL    actu… 2013-08-01   23.4    NA      NA   2013-08-01 Cons…
## 105        NA ACTUAL    actu… 2013-09-01   22      NA      NA   2013-09-01 Cons…
## 106        NA ACTUAL    actu… 2013-10-01   21.2    NA      NA   2013-10-01 Cons…
## 107        NA ACTUAL    actu… 2013-11-01   21      NA      NA   2013-11-01 Cons…
## 108        NA ACTUAL    actu… 2013-12-01   20.1    NA      NA   2013-12-01 Cons…
## 109        NA ACTUAL    actu… 2014-01-01   21.2    NA      NA   2014-01-01 Cons…
## 110        NA ACTUAL    actu… 2014-02-01   21.1    NA      NA   2014-02-01 Cons…
## 111        NA ACTUAL    actu… 2014-03-01   19.9    NA      NA   2014-03-01 Cons…
## 112        NA ACTUAL    actu… 2014-04-01   19      NA      NA   2014-04-01 Cons…
## 113        NA ACTUAL    actu… 2014-05-01   18      NA      NA   2014-05-01 Cons…
## 114        NA ACTUAL    actu… 2014-06-01   16.9    NA      NA   2014-06-01 Cons…
## 115        NA ACTUAL    actu… 2014-07-01   19.2    NA      NA   2014-07-01 Cons…
## 116        NA ACTUAL    actu… 2014-08-01   20.7    NA      NA   2014-08-01 Cons…
## 117        NA ACTUAL    actu… 2014-09-01   18.9    NA      NA   2014-09-01 Cons…
## 118        NA ACTUAL    actu… 2014-10-01   19.8    NA      NA   2014-10-01 Cons…
## 119        NA ACTUAL    actu… 2014-11-01   19.3    NA      NA   2014-11-01 Cons…
## 120        NA ACTUAL    actu… 2014-12-01   18.5    NA      NA   2014-12-01 Cons…
## 121        NA ACTUAL    actu… 2015-01-01   19.9    NA      NA   2015-01-01 Cons…
## 122        NA ACTUAL    actu… 2015-02-01   20.6    NA      NA   2015-02-01 Cons…
## 123        NA ACTUAL    actu… 2015-03-01   19.3    NA      NA   2015-03-01 Cons…
## 124        NA ACTUAL    actu… 2015-04-01   19.6    NA      NA   2015-04-01 Cons…
## 125        NA ACTUAL    actu… 2015-05-01   17.5    NA      NA   2015-05-01 Cons…
## 126        NA ACTUAL    actu… 2015-06-01   17.8    NA      NA   2015-06-01 Cons…
## 127        NA ACTUAL    actu… 2015-07-01   20.7    NA      NA   2015-07-01 Cons…
## 128        NA ACTUAL    actu… 2015-08-01   22.6    NA      NA   2015-08-01 Cons…
## 129        NA ACTUAL    actu… 2015-09-01   19.1    NA      NA   2015-09-01 Cons…
## 130        NA ACTUAL    actu… 2015-10-01   18.7    NA      NA   2015-10-01 Cons…
## 131        NA ACTUAL    actu… 2015-11-01   18.4    NA      NA   2015-11-01 Cons…
## 132        NA ACTUAL    actu… 2015-12-01   18.8    NA      NA   2015-12-01 Cons…
## 133        NA ACTUAL    actu… 2016-01-01   19.2    NA      NA   2016-01-01 Cons…
## 134        NA ACTUAL    actu… 2016-02-01   19.1    NA      NA   2016-02-01 Cons…
## 135        NA ACTUAL    actu… 2016-03-01   18.9    NA      NA   2016-03-01 Cons…
## 136        NA ACTUAL    actu… 2016-04-01   19.1    NA      NA   2016-04-01 Cons…
## 137        NA ACTUAL    actu… 2016-05-01   17.6    NA      NA   2016-05-01 Cons…
## 138        NA ACTUAL    actu… 2016-06-01   17.4    NA      NA   2016-06-01 Cons…
## 139        NA ACTUAL    actu… 2016-07-01   19.5    NA      NA   2016-07-01 Cons…
## 140        NA ACTUAL    actu… 2016-08-01   21.7    NA      NA   2016-08-01 Cons…
## 141        NA ACTUAL    actu… 2016-09-01   20      NA      NA   2016-09-01 Cons…
## 142        NA ACTUAL    actu… 2016-10-01   22.2    NA      NA   2016-10-01 Cons…
## 143        NA ACTUAL    actu… 2016-11-01   19.7    NA      NA   2016-11-01 Cons…
## 144        NA ACTUAL    actu… 2016-12-01   19.9    NA      NA   2016-12-01 Cons…
## 145        NA ACTUAL    actu… 2017-01-01   21      NA      NA   2017-01-01 Cons…
## 146        NA ACTUAL    actu… 2017-02-01   21.8    NA      NA   2017-02-01 Cons…
## 147        NA ACTUAL    actu… 2017-03-01   19.7    NA      NA   2017-03-01 Cons…
## 148        NA ACTUAL    actu… 2017-04-01   19.8    NA      NA   2017-04-01 Cons…
## 149        NA ACTUAL    actu… 2017-05-01   18.4    NA      NA   2017-05-01 Cons…
## 150        NA ACTUAL    actu… 2017-06-01   20.2    NA      NA   2017-06-01 Cons…
## 151        NA ACTUAL    actu… 2017-07-01   22      NA      NA   2017-07-01 Cons…
## 152        NA ACTUAL    actu… 2017-08-01   24.1    NA      NA   2017-08-01 Cons…
## 153        NA ACTUAL    actu… 2017-09-01   21.1    NA      NA   2017-09-01 Cons…
## 154        NA ACTUAL    actu… 2017-10-01   20.5    NA      NA   2017-10-01 Cons…
## 155        NA ACTUAL    actu… 2017-11-01   21.3    NA      NA   2017-11-01 Cons…
## 156        NA ACTUAL    actu… 2017-12-01   21.4    NA      NA   2017-12-01 Cons…
## 157        NA ACTUAL    actu… 2018-01-01   22      NA      NA   2018-01-01 Cons…
## 158        NA ACTUAL    actu… 2018-02-01   20.8    NA      NA   2018-02-01 Cons…
## 159        NA ACTUAL    actu… 2018-03-01   26.7    NA      NA   2018-03-01 Cons…
## 160        NA ACTUAL    actu… 2018-04-01   24.2    NA      NA   2018-04-01 Cons…
## 161        NA ACTUAL    actu… 2018-05-01   21.4    NA      NA   2018-05-01 Cons…
## 162        NA ACTUAL    actu… 2018-06-01   21.6    NA      NA   2018-06-01 Cons…
## 163        NA ACTUAL    actu… 2018-07-01   21.7    NA      NA   2018-07-01 Cons…
## 164        NA ACTUAL    actu… 2018-08-01   29.7    NA      NA   2018-08-01 Cons…
## 165        NA ACTUAL    actu… 2018-09-01   24.4    NA      NA   2018-09-01 Cons…
## 166        NA ACTUAL    actu… 2018-10-01   19.4    NA      NA   2018-10-01 Cons…
## 167        NA ACTUAL    actu… 2018-11-01   27.1    NA      NA   2018-11-01 Cons…
## 168        NA ACTUAL    actu… 2018-12-01   24.6    NA      NA   2018-12-01 Cons…
## 169        NA ACTUAL    actu… 2019-01-01   23.6    NA      NA   2019-01-01 Cons…
## 170        NA ACTUAL    actu… 2019-02-01   26.9    NA      NA   2019-02-01 Cons…
## 171        NA ACTUAL    actu… 2019-03-01   20.6    NA      NA   2019-03-01 Cons…
## 172        NA ACTUAL    actu… 2019-04-01   22.7    NA      NA   2019-04-01 Cons…
## 173        NA ACTUAL    actu… 2019-05-01   21      NA      NA   2019-05-01 Cons…
## 174        NA ACTUAL    actu… 2019-06-01   21.3    NA      NA   2019-06-01 Cons…
## 175        NA ACTUAL    actu… 2019-07-01   23.1    NA      NA   2019-07-01 Cons…
## 176        NA ACTUAL    actu… 2019-08-01   27.2    NA      NA   2019-08-01 Cons…
## 177        NA ACTUAL    actu… 2019-09-01   25.5    NA      NA   2019-09-01 Cons…
## 178        NA ACTUAL    actu… 2019-10-01   23      NA      NA   2019-10-01 Cons…
## 179        NA ACTUAL    actu… 2019-11-01   24.5    NA      NA   2019-11-01 Cons…
## 180        NA ACTUAL    actu… 2019-12-01   22.2    NA      NA   2019-12-01 Cons…
## 181        NA ACTUAL    actu… 2020-01-01   23.6    NA      NA   2020-01-01 Cons…
## 182        NA ACTUAL    actu… 2020-02-01   24.2    NA      NA   2020-02-01 Cons…
## 183        NA ACTUAL    actu… 2020-03-01   23.2    NA      NA   2020-03-01 Cons…
## 184        NA ACTUAL    actu… 2020-04-01   19.8    NA      NA   2020-04-01 Cons…
## 185        NA ACTUAL    actu… 2020-05-01   18.8    NA      NA   2020-05-01 Cons…
## 186        NA ACTUAL    actu… 2020-06-01   16.2    NA      NA   2020-06-01 Cons…
## 187        NA ACTUAL    actu… 2020-07-01   24.5    NA      NA   2020-07-01 Cons…
## 188        NA ACTUAL    actu… 2020-08-01   26      NA      NA   2020-08-01 Cons…
## 189        NA ACTUAL    actu… 2020-09-01   26      NA      NA   2020-09-01 Cons…
## 190        NA ACTUAL    actu… 2020-10-01   23.6    NA      NA   2020-10-01 Cons…
## 191        NA ACTUAL    actu… 2020-11-01   21.9    NA      NA   2020-11-01 Cons…
## 192         9 RECIPE_1… pred… 2020-12-01   24.0    20.5    27.6 2020-12-01 Cons…
## 193         9 RECIPE_1… pred… 2021-01-01   24.0    20.5    27.6 2021-01-01 Cons…
## 194         9 RECIPE_1… pred… 2021-02-01   24.0    20.5    27.6 2021-02-01 Cons…
## 195         9 RECIPE_1… pred… 2021-03-01   24.0    20.5    27.6 2021-03-01 Cons…
## 196         9 RECIPE_1… pred… 2021-04-01   24.0    20.5    27.6 2021-04-01 Cons…
## 197         9 RECIPE_1… pred… 2021-05-01   24.0    20.5    27.6 2021-05-01 Cons…
## # … with 2 more variables: value <dbl>, anomaly <dbl>, and abbreviated variable
## #   names ¹​.model_desc, ²​.conf_lo, ³​.conf_hi

予測値を含んだ時系列をセクターごとに可視化する。これがベースラインモデルとなる。

# final_baseline_models %>% 
#   ggplot(aes(.index, .value, col = id)) + 
#   geom_line() + 
#   geom_ribbon(aes(ymin = .conf_lo, ymax = .conf_hi), alpha = 0.1) +
#   geom_vline(xintercept = as.Date("2020-12-01")) + 
#   theme_bw() + 
#   scale_x_date(limits = c(as.Date("2005-01-01"), as.Date("2021-05-01")),
#                labels = date_format("%Y/%m"),
#                breaks = date_breaks("3 month")) + 
#   theme(axis.text.x = element_text(angle = 45, vjust = 0.2, hjust=0.2))

final_baseline_models %>% 
  dplyr::group_by(id) %>%
  plot_modeltime_forecast(
    .interactive = FALSE,
    .facet_ncol  = 3
  )

モデルの改善

ベースモデルの作成だけで割とお腹いっぱいであるが、先程のモデルよりも優れたモデルを作成する。データ分割を実行すると、下記のインフォメーションが表示されるが、問題ない。

Overlapping Timestamps Detected. Processing overlapping time series together using sliding windows.

最適なハイパーパラメータを見つけるために必要なクロスバリデーションデータを生成する。可視化された表では、すべてのセクターの系列が含まれているためイメージとは違うかもしれないが、ここでは問題ない。

resamples <- training(splits) %>%
  time_series_cv(
    date_var    = date, 
    assess      = "6 months",
    cumulative  = TRUE,
    skip        = "3 months", 
    slice_limit = 5
  )

resamples %>%
  tk_time_series_cv_plan() %>% 
  plot_time_series_cv_plan(.date_var = date, .value = value)

各フォールドの詳細は下記の通り。

resamples %>% 
  mutate(
    analysis = map(.x = splits, .f = function(x){analysis(x)}),
    assessment = map(.x = splits, .f = function(x){assessment(x)}),
    analysis_min_date = map(.x = analysis, .f = function(x){min(x$date)}),
    analysis_max_date = map(.x = analysis, .f = function(x){max(x$date)}),
    assessment_min_date = map(.x = assessment, .f = function(x){min(x$date)}),
    assessment_max_date = map(.x = assessment, .f = function(x){max(x$date)}),
  ) %>% 
  unnest(analysis_min_date,
         analysis_max_date,
         assessment_min_date,
         assessment_max_date
         )
## # A tibble: 5 × 8
##   splits            id     analysis assessment analysis_…¹ analysis…² assessme…³
##   <list>            <chr>  <list>   <list>     <date>      <date>     <date>    
## 1 <split [2405/78]> Slice1 <tibble> <tibble>   2005-01-01  2020-05-01 2020-06-01
## 2 <split [2366/78]> Slice2 <tibble> <tibble>   2005-01-01  2020-02-01 2020-03-01
## 3 <split [2327/78]> Slice3 <tibble> <tibble>   2005-01-01  2019-11-01 2019-12-01
## 4 <split [2288/78]> Slice4 <tibble> <tibble>   2005-01-01  2019-08-01 2019-09-01
## 5 <split [2249/78]> Slice5 <tibble> <tibble>   2005-01-01  2019-05-01 2019-06-01
## # … with 1 more variable: assessment_max_date <date>, and abbreviated variable
## #   names ¹​analysis_min_date, ²​analysis_max_date, ³​assessment_min_date

次はモデルを設定する。今回はProphetBoostモデルを利用する。

model_prophet_boost <- modeltime::prophet_boost(
    # prophet
    growth = "linear",
    changepoint_num = tune(),
    changepoint_range = tune(),
    seasonality_yearly = TRUE,
    seasonality_weekly = FALSE, # Monthlyデータなので機能しない
    seasonality_daily  = FALSE, # Monthlyデータなので機能しない
    season = "additive",
    prior_scale_changepoints = tune(),
    prior_scale_seasonality = tune(),
    # prior_scale_holidays = NULL,
    # xgboost
    trees = 1000,
    sample_size = c(0.5, 1),
    mtry = tune(),  
    tree_depth = tune(),
    learn_rate = tune(),
    stop_iter = tune(),
    min_n = tune(),
    # loss_reduction = tune(),
  ) %>%
  set_engine('prophet_xgboost')

model_prophet_boost
## PROPHET Regression Model Specification (regression)
## 
## Main Arguments:
##   growth = linear
##   changepoint_num = tune()
##   changepoint_range = tune()
##   seasonality_yearly = TRUE
##   seasonality_weekly = FALSE
##   seasonality_daily = FALSE
##   season = additive
##   prior_scale_changepoints = tune()
##   prior_scale_seasonality = tune()
##   mtry = tune()
##   trees = 1000
##   min_n = tune()
##   tree_depth = tune()
##   learn_rate = tune()
##   sample_size = c(0.5, 1)
##   stop_iter = tune()
## 
## Computational engine: prophet_xgboost

モデルの次はレシピの設定を行なう。

recipe_prophet_boost <- recipe(value ~ id + date + anomaly, data = training(splits)) %>%
  step_timeseries_signature(date) %>%
  step_rm(matches("(.iso$)|(.xts$)|(day)|(hour)|(minute)|(second)|(am.pm)")) %>%
  step_rm("date_index.num") %>%
  step_mutate(date_month = factor(date_month, ordered = TRUE)) %>%
  step_dummy(all_nominal(), one_hot = TRUE)

recipe_prophet_boost %>% prep() %>% bake(training(splits))
## # A tibble: 2,483 × 48
##    date       anomaly value date_year date_half date_q…¹ date_…² date_…³ date_…⁴
##    <date>       <dbl> <dbl>     <int>     <int>    <int>   <int>   <int>   <int>
##  1 2005-01-01       0  24.1      2005         1        1       1       1       1
##  2 2005-01-01       1  96        2005         1        1       1       1       1
##  3 2005-01-01       0  13.4      2005         1        1       1       1       1
##  4 2005-01-01       0  29        2005         1        1       1       1       1
##  5 2005-01-01       1  67.2      2005         1        1       1       1       1
##  6 2005-01-01       0  32.3      2005         1        1       1       1       1
##  7 2005-01-01       1 360.       2005         1        1       1       1       1
##  8 2005-01-01       0  48.7      2005         1        1       1       1       1
##  9 2005-01-01       0 119.       2005         1        1       1       1       1
## 10 2005-01-01       1 134.       2005         1        1       1       1       1
## # … with 2,473 more rows, 39 more variables: date_week3 <int>,
## #   date_week4 <int>, id_AlimBegudaTabac <dbl>, id_AltresIndus <dbl>,
## #   id_AltresMatConstr <dbl>, id_CimentsCalGuix <dbl>, id_ConsObrPub <dbl>,
## #   id_ConstrMedTrans <dbl>, id_IndusVidre <dbl>, id_Metalurgia <dbl>,
## #   id_PastaPaperCartro <dbl>, id_QuimPetroquim <dbl>,
## #   id_RestaTransforMetal <dbl>, id_SiderFoneria <dbl>,
## #   id_TextilConfecCuirCalçat <dbl>, date_month_01 <dbl>, …

モデルとレシピをワークフローに設定する。

workflow_prophet_boost <- workflow() %>%
    add_model(model_prophet_boost) %>%
    add_recipe(recipe_prophet_boost)

そして、tune_grid関数を使用して、パラメータの最適値を確認する。このプロセスは時間がかかるので、control_grid関数を介して並列計算オプションを有効する(allow_par = TRUE)。前回に引き続き理解が甘いせいでワーニングが出るが、ここらへんは次回以降で調べる予定。

set.seed(1989)
tune_results <- tune_grid(
    object     = workflow_prophet_boost,
    resamples  = resamples,
    param_info = extract_parameter_set_dials(workflow_prophet_boost),
    grid       = 20,
    control    = control_grid(verbose = FALSE, 
                              allow_par = TRUE, 
                              parallel_over = "everything")
    )

rmseを最小にするパラメタの組み合わせ上位10は下記の通り。

tune_results %>% 
  show_best(n = 10, metric = "rmse") %>% 
  datatable()

ベストなパラメタを抜き出しておき、

tuned_best <- tune_results %>%
    select_best("rmse")
tuned_best
## # A tibble: 1 × 10
##   changepo…¹ chang…² prior…³ prior…⁴  mtry min_n tree_…⁵ learn…⁶ stop_…⁷ .config
##        <int>   <dbl>   <dbl>   <dbl> <int> <int>   <int>   <dbl>   <int> <chr>  
## 1         26   0.804  0.0710  0.0203    37    40      10  0.0275      16 Prepro…
## # … with abbreviated variable names ¹​changepoint_num, ²​changepoint_range,
## #   ³​prior_scale_changepoints, ⁴​prior_scale_seasonality, ⁵​tree_depth,
## #   ⁶​learn_rate, ⁷​stop_iter

ワークフローを先程のパラメタで更新する。モデルテーブルに登録する必要があるので、とりあえずフィッティングしておく。

finalize_workflow_prophet_boost <- workflow_prophet_boost %>%
    finalize_workflow(parameters = tuned_best)

# ここのデータはなんでも
finalize_workflow_fit_prophet_boost <- finalize_workflow_prophet_boost %>%
    fit(training(resamples$splits[[1]])) 

finalize_workflow_fit_prophet_boost
## ══ Workflow [trained] ══════════════════════════════════════════════════════════
## Preprocessor: Recipe
## Model: prophet_boost()
## 
## ── Preprocessor ────────────────────────────────────────────────────────────────
## 5 Recipe Steps
## 
## • step_timeseries_signature()
## • step_rm()
## • step_rm()
## • step_mutate()
## • step_dummy()
## 
## ── Model ───────────────────────────────────────────────────────────────────────
## PROPHET w/ XGBoost Errors
## ---
## Model 1: PROPHET
##  - growth: 'linear'
##  - n.changepoints: 26
##  - changepoint.range: 0.804211583290016
##  - yearly.seasonality: 'TRUE'
##  - weekly.seasonality: 'FALSE'
##  - daily.seasonality: 'FALSE'
##  - seasonality.mode: 'additive'
##  - changepoint.prior.scale: 0.0710013850400473
##  - seasonality.prior.scale: 0.0203178121553851
##  - holidays.prior.scale: 10
##  - logistic_cap: NULL
##  - logistic_floor: NULL
## 
## ---
## Model 2: XGBoost Errors
## 
## xgboost::xgb.train(params = list(eta = 0.0274961874053855, max_depth = 10L, 
##     gamma = 0, colsample_bytree = 1, colsample_bynode = 0.822222222222222, 
##     min_child_weight = 40L, subsample = c(0.5, 1)), data = x$data, 
##     nrounds = 1000, watchlist = x$watchlist, verbose = 0, early_stopping_rounds = 16L, 
##     objective = "reg:squarederror", nthread = 1)

finalize_workflow_prophet_boostモデルをモデルテーブルに登録し、予測値を算出する。

data_forecasted_prophet_boost <- modeltime_table(
  finalize_workflow_fit_prophet_boost
  ) %>%
    # confを計算するために必要
    modeltime_calibrate(testing(splits), id = "id") %>%
    modeltime_forecast(
        new_data = testing(splits),
        actual_data = df,
        conf_by_id = TRUE,
        keep_data = TRUE
    ) 
# data_forecasted_prophet_boost %>% filter(id == "ConsObrPub") 
data_forecasted_prophet_boost %>% 
  DT::datatable()

テストデータに対する予測値を可視化しておく。ベースラインモデルよりは可視化だけでも良いモデルとわかる。

data_forecasted_prophet_boost %>% 
  group_by(id) %>% 
  plot_modeltime_forecast(
    .interactive = TRUE, 
    .legend_show = FALSE,
    .facet_ncol = 3
    )

このモデルのグローバルモデルの精度は、下記の通り。

modeltime_table(finalize_workflow_fit_prophet_boost) %>%
    modeltime_calibrate(testing(splits), id = "id") %>%
    modeltime_accuracy(acc_by_id = FALSE) %>%
    table_modeltime_accuracy(.expand_groups = FALSE)

ローカルモデルの精度は、下記の通り。

modeltime_table(finalize_workflow_fit_prophet_boost) %>%
    modeltime_calibrate(testing(splits), id = "id") %>%
    modeltime_accuracy(acc_by_id = TRUE) %>%
    table_modeltime_accuracy(.expand_groups = FALSE)

modeltime_refit関数でフルデータで再学習して、予測期間で予測をする、ということはこのモデルからはできない。理由はanomalyというカラムが将来日付に存在していないが、学習時にモデルに利用しているため。