Search code examples
rtime-seriesforecastingarimafable-r

new_transformation not working with multiple inputs from tsibble object inside ARIMA


I am working on exercise #4 from this book.

https://otexts.com/fpp3/dynamic-exercises.html

I am trying to create a transformation to adjust for CPI, however, it appears because I am passing two variables from the tsibble object into my transformation function, it does not recognize it as a transformation of the data, but rather as a new data series. Any idea how to correct?

library(fpp3)

cpi_adj <- function(data, cpi) {
  return(data/cpi*100)
}

cpi_unadj <- function(data, cpi) {
  return(data*cpi/100)
}

cpi_trans <- new_transformation(cpi_adj, cpi_unadj)

aus_acc_fit <- aus_accommodation %>% 
  model(ARIMA(cpi_trans(Takings, CPI) ~ trend(knots = yearquarter("2008 Q1")) + season()))

aus_acc_fit %>% 
  filter(State == "Victoria") %>%
  report()

This is the output I get and you can see in the header of the model summary, rather than recognizing it as a transformation, it recognizes it as a new data series instead.

Series: cpi_trans(Takings, CPI) 
Model: LM w/ ARIMA(1,0,0)(0,0,1)[4] errors 

Coefficients:
         ar1    sma1  trend(knots = yearquarter("2008 Q1"))trend  trend(knots = yearquarter("2008 Q1"))trend_41  season()year2  season()year3  season()year4  intercept
      0.6596  0.3756                                      3.1995                                         0.3892       -57.8760       -36.0249       -12.9360   264.4398
s.e.  0.0866  0.1242                                      0.4871                                         0.9790         3.9693         4.6151         4.0447    13.3769

sigma^2 estimated as 170.8:  log likelihood=-291.63
AIC=601.26   AICc=604.07   BIC=622

Solution

  • {fable} will attempt to identify the response variable from your left hand side based on the length of the variables. Since both Takings and CPI have the same variable length, it cannot distinguish if you were trying to forecast Takings or CPI - so it instead forecasts cpi_trans(Takings, CPI).

    To explicitly define which variable is the response, you can use the resp() function.

    Also note that for simpler transformations like yours, it is possible to directly write the transformation on the left side of the formula. For example: ARIMA(resp(Takings)/CPI*100 ~ trend(knots = yearquarter("2008 Q1")) + season())

    library(fpp3)
    cpi_adj <- function(data, cpi) {
      return(data/cpi*100)
    }
    
    cpi_unadj <- function(data, cpi) {
      return(data*cpi/100)
    }
    
    cpi_trans <- new_transformation(cpi_adj, cpi_unadj)
    
    aus_acc_fit <- aus_accommodation %>% 
      model(ARIMA(cpi_trans(resp(Takings), CPI) ~ trend(knots = yearquarter("2008 Q1")) + season()))
    
    aus_acc_fit %>% 
      filter(State == "Victoria") %>%
      report()
    #> Series: Takings 
    #> Model: LM w/ ARIMA(1,0,0)(0,0,1)[4] errors 
    #> Transformation: cpi_trans(Takings, CPI) 
    #> 
    #> Coefficients:
    #>          ar1    sma1  trend(knots = yearquarter("2008 Q1"))trend
    #>       0.6596  0.3756                                      3.1995
    #> s.e.  0.0866  0.1242                                      0.4871
    #>       trend(knots = yearquarter("2008 Q1"))trend_41  season()year2
    #>                                              0.3892       -57.8760
    #> s.e.                                         0.9790         3.9693
    #>       season()year3  season()year4  intercept
    #>            -36.0249       -12.9360   264.4398
    #> s.e.         4.6151         4.0447    13.3769
    #> 
    #> sigma^2 estimated as 170.8:  log likelihood=-291.63
    #> AIC=601.26   AICc=604.07   BIC=622
    

    Created on 2022-07-28 by the reprex package (v2.0.1)