4

Let's say I have some models stored in a list:

mods <- list()
mods[[1]] <- lm(mpg ~ disp, data = mtcars)
mods[[2]] <- lm(mpg ~ disp + factor(cyl), data = mtcars)
mods[[3]] <- lm(mpg ~ disp * factor(cyl), data = mtcars)

And I want to compare them using stats::AIC. I'm looking for the output I would get from AIC(mods[[1]], mods[[2]], mods[[3]]), but I'd like it to generalize to an arbitrarily long list. I thought that

do.call(AIC, mods)

would work, but it returns something that's very verbose and unhelpful. (If the list is named, an error results unless one of the names is object, corresponding the the first argument of AIC, but then you just get the verbose output again.)

After the failure of do.call, I started thinking about an eval(parse()) solution, but I figured I should ask here first.

Gregor Thomas
  • 104,719
  • 16
  • 140
  • 257

2 Answers2

4
summary(do.call(AIC, mods))
       df         AIC       
 Min.   :3   Min.   :153.4  
 1st Qu.:4   1st Qu.:159.6  
 Median :5   Median :165.8  
 Mean   :5   Mean   :163.1  
 3rd Qu.:6   3rd Qu.:168.0  
 Max.   :7   Max.   :170.2  

But this likely isn't what you want. Baptiste has the answer:

my.aic <- function(x) {
  x <- do.call(AIC, x)
  rownames(x) <- NULL
  return(x)
}
my.aic(mods)
##   df      AIC
## 1  3 170.2094
## 2  5 165.7680
## 3  7 153.4352

This is rather close to:

AIC(mods[[1]], mods[[2]], mods[[3]])
##           df      AIC
## mods[[1]]  3 170.2094
## mods[[2]]  5 165.7680
## mods[[3]]  7 153.4352
Matthew Lundberg
  • 39,899
  • 6
  • 81
  • 105
  • After using this for a bit, I'll say that it can disappointingly slow. The rownames that are put in by default can be gigantic, and they are then slow even just to remove. Although this answer seems like the "right" way to do it, I've switched back to the hack-ish `eval(parse())` solution in my answer. – Gregor Thomas Aug 27 '13 at 17:33
2

Here's a solution using eval(parse()). Luckily Matthew gave a better answer before I even had this typed up.

AIC_l <- function(L, FUN = "AIC") {
    args <- paste0("mods[[", seq_along(L), "]]", collapse = ", ")
    my_call <- paste0(FUN, "(", args, ")")
    eval(parse(text = my_call))
}
AIC_l(L = 1:3, FUN = "AIC")
user63230
  • 2,459
  • 11
  • 24
Gregor Thomas
  • 104,719
  • 16
  • 140
  • 257