如何将列表的每个元素作为未命名的参数传递给函数?

时间:2013-05-19 02:02:18

标签: r do.call

假设我有一些模型存储在列表中:

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)

我希望使用stats::AIC来比较它们。我正在寻找我从AIC(mods[[1]], mods[[2]], mods[[3]])获得的输出,但我希望它可以推广到任意长的列表。我以为

do.call(AIC, mods)

会起作用,但它会返回一些非常冗长且无益的东西。 (如果列表已命名,则会产生错误,除非其中一个名称为object,对应AIC的第一个参数,但您只是再次获得详细输出。)

do.call失败后,我开始考虑eval(parse())解决方案,但我想我应先问这里。

2 个答案:

答案 0 :(得分: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  

但这可能不是你想要的。巴蒂斯特有答案:

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

这非常接近:

AIC(mods[[1]], mods[[2]], mods[[3]])
##           df      AIC
## mods[[1]]  3 170.2094
## mods[[2]]  5 165.7680
## mods[[3]]  7 153.4352

答案 1 :(得分:1)

以下是使用eval(parse())的解决方案。幸运的是,在我打开这个类型之前,马修给出了一个更好的答案。

AIC_l <- function(L, FUN = "AIC") {
    args <- paste0("mods[[", seq_along(L), "]]", collapse = ", ")
    my_call <- paste0(FUN, "(", args, ")")
    eval(parse(text = my_call))
}