Search code examples
rtime-seriesmodel-comparison

Sorting ARIMA AIC in R


I have the following code which returns the model with the lowest AIC, but I want all the models with their AIC in ascending or descending order without using the built-in sort function in R

sp <- rnorm(100)  ## just some toy data to make code work!
spfinal.aic <- Inf
spfinal.order <- c(0,0,0)
for (p in 1:4) for (d in 0:1) for (q in 1:4) {
  spcurrent.aic <- AIC(arima(sp, order=c(p, d, q)))
   if (spcurrent.aic < spfinal.aic) {
     spfinal.aic <- spcurrent.aic
     spfinal.order <- c(p, d, q)
     spfinal.arima <- arima(sp, order=spfinal.order)
   }
}

I want spfinal.order<-c(p,d,p) to be a list of all models in ascending or descending order of AIC. How can I do that?


Solution

  • The code below does what you want. As you want a record of all models having been tried, no comparison is done inside the loop. A vector aic.vec will hold AIC values of all models, while a matrix order.matrix will hold column-by-column the ARIMA specification. In the end, we sort both by ascending AIC values, so that you know the best model is the first one.

    sp <- rnorm(100)  ## just some toy data to make code work!
    order.matrix <- matrix(0, nrow = 3, ncol = 4 * 2 * 4)
    aic.vec <- numeric(4 * 2 * 4)
    k <- 1
    for (p in 1:4) for (d in 0:1) for (q in 1:4) {
      order.matrix[, k] <- c(p,d,q)
      aic.vec[k] <- AIC(arima(sp, order=c(p, d, q)))
      k <- k+1
      }
    ind <- order(aic.vec, decreasing = FALSE)
    aic.vec <- aic.vec[ind]
    order.matrix <- order.matrix[, ind]
    

    I did not use a list to store the ARIMA specification, because I think a matrix is better. At the moment the matrix is in wide format, i.e., with 3 rows while many columns. You can transpose it for better printing:

    order.matrix <- t(order.matrix)
    

    Maybe you also want to bind order.matrix and aic.vec together for better presentation? Do this:

    result <- cbind(order.matrix, aic.vec)
    colnames(result) <- c("p", "d", "q", "AIC")
    

    I think this makes it easier for you to inspect. Example output (first 5 rows):

    > result
          p d q      AIC
     [1,] 2 0 2 305.5698
     [2,] 3 0 3 305.8882
     [3,] 1 0 3 307.8365
     [4,] 2 1 3 307.9137
     [5,] 1 1 2 307.9952