Skip to contents

Compares the first row of res$table with the incumbent model recorded by auto_seasonal_analysis(). The candidate must improve comparable AICc by a material amount, pass absolute residual diagnostics, avoid material deterioration relative to the incumbent, and satisfy the existing distance and seasonal-correlation safeguards. Identical adjusted series are kept.

Usage

sa_should_switch(
  res,
  thresholds = list(min_qs_p = 0.1, max_dist_sa_mult = 1.25, min_corr_seas = 0.9,
    min_lb_p = 0.05, min_delta_aicc = 2, max_qs_p_drop = 0.05, max_lb_p_drop = 0.05,
    identical_sa_tolerance = 1e-08),
  current_model = NULL,
  details = FALSE
)

Arguments

res

Result of auto_seasonal_analysis().

thresholds

Named list with decision thresholds:

  • min_qs_p: minimum acceptable QS p-value on SA (overall) for the best model

  • max_dist_sa_mult: allow SA L1 distance up to this multiple of the cross-candidate median

  • min_corr_seas: minimum correlation of seasonal components (vs. incumbent)

  • min_lb_p: minimum acceptable Ljung-Box p-value on residuals

  • min_delta_aicc: minimum incumbent-minus-candidate AICc improvement

  • max_qs_p_drop: maximum allowed decline in QS p-value vs. incumbent

  • max_lb_p_drop: maximum allowed decline in Ljung-Box p-value vs. incumbent

  • identical_sa_tolerance: relative tolerance used to identify equal adjusted series

current_model

Optional fitted seasonal::seas incumbent. This is useful for older result objects that do not contain baseline diagnostics.

details

Logical. If FALSE (default), return only the decision string. If TRUE, return a list containing decision, reason, and metrics.

Value

One of "CHANGE_TO_NEW_MODEL", "KEEP_CURRENT_MODEL", "REVIEW_REQUIRED", or "NO_BASELINE"; with details = TRUE, a structured list containing the decision and its supporting evidence.

Examples

# \donttest{
if (requireNamespace("seasonal", quietly = TRUE)) {
  current_model <- seasonal::seas(AirPassengers)
  res <- auto_seasonal_analysis(
    AirPassengers,
    current_model = current_model,
    max_specs = 3
  )
  sa_should_switch(res)
}
#> Model used in SEATS is different: (1 1 2)(1 0 0)
#> Model used in SEATS is different: (1 1 2)(1 0 0)
#> Model used in SEATS is different: (1 1 1)(1 0 0)
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(0 1 0)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[8]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(0 1 0)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[8]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(1 1 1)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[8]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(1 1 1)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[8]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(0 1 1)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[1]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> seas(
#>   x = structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301,  356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432), tsp = c(1949, 1960.91666666667, 12), class = "ts"),
#>   seats.noadmiss = "no",
#>   transform.function = "log",
#>   arima.model = "(0 1 1)(0 1 1)",
#>   seats = "",
#>   regression.variables = "easter[1]",
#>   regression.aictest = NULL,
#>   outlier = NULL
#> )
#> Model used in SEATS is different: (0 1 1)(0 0 1)
#> [1] "KEEP_CURRENT_MODEL"
# }