【问题标题】:Using lapply on a list of models在模型列表上使用 lapply
【发布时间】:2013-02-16 20:09:32
【问题描述】:

我已经生成了一个模型列表,并想创建一个汇总表。

作为示例,这里有两个模型:

x <- seq(1:10)
y <- sin(x)^2
model1 <- lm(y ~ x)
model2 <- lm(y ~ x + I(x^2) + I(x^3))

和两个公式,第一个从公式的分量生成方程

get.model.equation <- function(x) {
  x <- as.character((x$call)$formula)
  x <- paste(x[2],x[1],x[3])
}

第二个生成模型名称作为字符串

get.model.name <- function(x) {
  x <- deparse(substitute(x))
}

有了这些,我创建了一个汇总表

model.list <- list(model1, model2)
AIC.data <- lapply(X = model.list, FUN = AIC)
AIC.data <- as.numeric(AIC.data)
model.models <- lapply(X = model.list, FUN = get.model)
model.summary <- cbind(model.models, AIC.data)
model.summary <- as.data.frame(model.summary)
names(model.summary) <- c("Model", "AIC")
model.summary$AIC <- unlist(model.summary$AIC)
rm(AIC.data)
model.summary[order(model.summary$AIC),]

一切正常。 我想使用 get.model.name 将模型名称添加到表中

x <- get.model.name(model1)

这给了我想要的“model1”。

所以现在我将函数应用于模型列表

model.names <- lapply(X = model.list, FUN = get.model.name)

但现在我得到的是 X[[1L]]

而不是 model1

我如何获得 model1 而不是 X[[1L]]

我在找一张像这样的桌子:

 Model                Formula       AIC
model1                  y ~ x  11.89136
model2 y ~ x + I(x^2) + I(x^3) 15.03888

【问题讨论】:

  • 您在model.list 中创建了一个未命名列表,并且您正在将此列表中的每个元素传递给get.model.name。所以,X[[1]] 确实是第一次通过,它会获取您所要求的内容。 @baptiste 通过简单地创建一个命名列表并避免复杂化来克服这个问题。如果他的解决方案不是您想要的,您可能必须解释为什么要这样做。
  • 感谢阿伦和巴蒂斯特。我已经添加了我想要制作的内容。
  • 再次感谢。在阅读了您的 cmets 后,我刚刚将 model.list &lt;- list(model1, model2) 替换为 model.list &lt;- list(model1=model1, model2=model2),它现在运行良好。

标签: r lapply


【解决方案1】:

你想要这样的东西吗?

model.list <- list(model1 = lm(y ~ x), 
                   model2 = lm(y ~ x + I(x^2) + I(x^3)))
sapply(X = model.list, FUN = AIC)

【讨论】:

    【解决方案2】:

    我会这样做:

    model.list <- list(model1 = lm(y ~ x),
                       model2 = lm(y ~ x + I(x^2) + I(x^3)))
    # changed Reduce('rbind', ...) to do.call(rbind, ...) (Hadley's comment)
    do.call(rbind, 
            lapply(names(model.list), function(x) 
              data.frame(model = x, 
              formula = get.model.equation(model.list[[x]]), 
              AIC = AIC(model.list[[x]])
              )
            )
          )
    
    #    model                 formula      AIC
    # 1 model1                   y ~ x 11.89136
    # 2 model2 y ~ x + I(x^2) + I(x^3) 15.03888
    

    【讨论】:

    • ldply 让这个模式变得更简单......(同样Reduce + rbind 对于大型列表来说效率很低)
    • 确实如此。感谢您指出Reduce。我使用do.call(rbind,...) 进行了编辑。
    【解决方案3】:

    另一个选项,ldply但请参阅下面 hadley 的评论以更有效地使用 ldply

     # prepare data
        x <- seq(1:10)
        y <- sin(x)^2
        dat <- data.frame(x,y)
    
    # create list of named models obviously these are not suited to the data here, just to make the workflow work...
    models <- list(model1=lm(y~x, data = dat), 
                   model2=lm(y~I(1/x), data=dat),
                   model3=lm(y ~ log(x), data = dat),
                   model4=nls(y ~ I(1/x*a) + b*x, data = dat, start = list(a = 1, b = 1)), 
                   model5=nls(y ~ (a + b*log(x)), data=dat, start = setNames(coef(lm(y ~ log(x), data=dat)), c("a", "b"))),
                   model6=nls(y ~ I(exp(1)^(a + b * x)), data=dat, start = list(a=0,b=0)),
                   model7=nls(y ~ I(1/x*a)+b, data=dat, start = list(a=1,b=1))
    )
    
    library(plyr)
    library(AICcmodavg) # for small sample sizes
    # build table with model names, function, AIC and AICc
    data.frame(cbind(ldply(models, function(x) cbind(AICc = AICc(x), AIC = AIC(x))), 
                     model = sapply(1:length(models), function(x) deparse(formula(models[[x]])))
                          ))
    
         .id     AICc      AIC                     model
    1 model1 15.89136 11.89136                     y ~ x
    2 model2 15.78480 11.78480                y ~ I(1/x)
    3 model3 15.80406 11.80406                y ~ log(x)
    4 model4 16.62157 12.62157    y ~ I(1/x * a) + b * x
    5 model5 15.80406 11.80406      y ~ (a + b * log(x))
    6 model6 15.88937 11.88937 y ~ I(exp(1)^(a + b * x))
    7 model7 15.78480 11.78480        y ~ I(1/x * a) + b
    

    ldply 函数中如何用列名替换.id 对我来说不是很明显,有什么提示吗?

    【讨论】:

    • 或者只是:ldply(models, function(mod) data.frame(AICc = AICc(mod), AIC = AIC(mod), model = deparse(formula(mod))) })
    • @hadley,谢谢,是的,这要简单得多(需要一个开括号才能使其工作)。你愿意从肮脏的把戏学校简化这个:stackoverflow.com/a/15104211/1036500 吗?
    • @本。感谢您很好地演示了这个问题。这是非常有用的。我想确定我们是否可以在此表中提取其他统计信息,例如 R2、Pvalue 等?如果是这样,如何将它转为 R?再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多