How do I pass every element of a list to a function as unnamed arguments?
Asked Answered
D

2

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.

Dremadremann answered 19/5, 2013 at 2:2 Comment(1)
can't you simply remove the rownames? (as in test = do.call(AIC, mods); rownames(test) = NULL)Babylonian
P
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
Penta answered 19/5, 2013 at 2:10 Comment(1)
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.Dremadremann
D
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")
Dremadremann answered 19/5, 2013 at 2:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.