【问题标题】:Export summary of multiple regressions from list从列表中导出多个回归的摘要
【发布时间】:2017-05-10 19:47:20
【问题描述】:

我有一个使用标准数据集mtcars 通过此代码完成的多重回归列表。

models <- lapply(paste("mpg", names(mtcars)[-1], sep = "~"), formula)
res.models <- lapply(models, FUN = function(x) {summary(lm(formula = x, data = mtcars))})
names(res.models) <- paste("mpg", names(mtcars)[-1], sep = "~")

我现在有一个针对第一列“mpg”的多重回归列表。从这里我试图导出某些汇总统计信息,例如;截距、系数和 r.squared。

我尝试过使用下面包含的循环。

for (i in 1:length(res.models))
{
  res <- res.models[[i]]
  res_bound <- NULL
  intercept <- res$coefficients[1]
  coef <- res$coefficients[2]
  r <- res$r.squared
  res_bound <- cbind(intercept, coef, r)
}

虽然这让我得到了dataframe,但它只包括最后一个回归模型的结果,即 1 行乘 3 列dataframe。此外,我希望在表中包含每个回归的“术语”,以区分我正在查看的模型(例如 mpg 与 cyl 或 mpg 与 hp)。

我只是错过了循环中的一步吗?最终目标是write.csv最终dataframe

【问题讨论】:

  • 我会使用lapply 来做你想要用for 做的事情,然后使用do.call(rbind, list)dplyr::bind_rows(list) 将列表元素组合到一个表中。基本上,编写一个适用于一个模型的函数,使用 lapply 对模型进行迭代,然后组合结果。
  • 作为一个建议,您是否考虑过使用broom::tidylm 输出转换为漂亮的数据帧?
  • @coffeinjunky 我用过这个函数是的,但它不输出 r.squared。如果可以包含 r.squared,那肯定会更好用
  • broom::glance 会这样做,您可以将其合并回来自broom::tidy 的数据框。
  • 另外,为了解决您的实际问题,在每次循环迭代中,您只有` res_bound , leaving you with res_bound`最后一次迭代。

标签: r regression lm


【解决方案1】:

您可以使用purrr::map_dfbroom::glance 应用于每个模型,然后将结果收集到data.frame:

purrr::map_df(res.models, broom::glance, .id = 'formula')
#>     formula r.squared adj.r.squared    sigma statistic      p.value df
#> 1   mpg~cyl 0.7261800     0.7170527 3.205902 79.561028 6.112687e-10  2
#> 2  mpg~disp 0.7183433     0.7089548 3.251454 76.512660 9.380327e-10  2
#> 3    mpg~hp 0.6024373     0.5891853 3.862962 45.459803 1.787835e-07  2
#> 4  mpg~drat 0.4639952     0.4461283 4.485409 25.969645 1.776240e-05  2
#> 5    mpg~wt 0.7528328     0.7445939 3.045882 91.375325 1.293959e-10  2
#> 6  mpg~qsec 0.1752963     0.1478062 5.563738  6.376702 1.708199e-02  2
#> 7    mpg~vs 0.4409477     0.4223126 4.580827 23.662241 3.415937e-05  2
#> 8    mpg~am 0.3597989     0.3384589 4.902029 16.860279 2.850207e-04  2
#> 9  mpg~gear 0.2306734     0.2050292 5.373695  8.995144 5.400948e-03  2
#> 10 mpg~carb 0.3035184     0.2803024 5.112961 13.073646 1.084446e-03  2

您可以对系数使用broom::tidy 或对残差使用broom::augment 执行类似的操作。请注意,扫帚函数旨在在模型本身上调用,而不是在摘要上调用,但如果您愿意,您可以将整个内容保存在管道中:

library(purrr)

names(mtcars)[-1] %>% 
    paste('mpg ~', .) %>%    # or start with `models` at this point
    map(lm, data = mtcars) %>% 
    map_df(broom::glance, .id = 'formula')
#>    formula r.squared adj.r.squared    sigma statistic      p.value df
#> 1        1 0.7261800     0.7170527 3.205902 79.561028 6.112687e-10  2
#> 2        2 0.7183433     0.7089548 3.251454 76.512660 9.380327e-10  2
#> 3        3 0.6024373     0.5891853 3.862962 45.459803 1.787835e-07  2
#> 4        4 0.4639952     0.4461283 4.485409 25.969645 1.776240e-05  2
#> 5        5 0.7528328     0.7445939 3.045882 91.375325 1.293959e-10  2
#> 6        6 0.1752963     0.1478062 5.563738  6.376702 1.708199e-02  2
#> 7        7 0.4409477     0.4223126 4.580827 23.662241 3.415937e-05  2
#> 8        8 0.3597989     0.3384589 4.902029 16.860279 2.850207e-04  2
#> 9        9 0.2306734     0.2050292 5.373695  8.995144 5.400948e-03  2
#> 10      10 0.3035184     0.2803024 5.112961 13.073646 1.084446e-03  2
#>       logLik      AIC      BIC deviance df.residual
#> 1  -81.65321 169.3064 173.7036 308.3342          30
#> 2  -82.10469 170.2094 174.6066 317.1587          30
#> 3  -87.61931 181.2386 185.6358 447.6743          30
#> 4  -92.39996 190.7999 195.1971 603.5667          30
#> 5  -80.01471 166.0294 170.4266 278.3219          30
#> 6  -99.29406 204.5881 208.9853 928.6553          30
#> 7  -93.07356 192.1471 196.5443 629.5193          30
#> 8  -95.24219 196.4844 200.8816 720.8966          30
#> 9  -98.18192 202.3638 206.7611 866.2980          30
#> 10 -96.59033 199.1807 203.5779 784.2711          30

请注意,您会得到一些不能包含在摘要中的额外变量。

【讨论】:

    【解决方案2】:

    如果你想在基础 R 中做到这一点:

    res <- lapply(seq_along(res.models), function(i) {
    
      data.frame(model = names(res.models)[i],
                 intercept = res.models[[i]]$coefficients[1],
                 coef = res.models[[i]]$coefficients[2],
                 r = res.models[[i]]$r.squared,
                 stringsAsFactors = FALSE)
    
    })
    
    do.call(rbind, res)
    

    输出:

          model intercept        coef         r
    1   mpg~cyl 37.884576 -2.87579014 0.7261800
    2  mpg~disp 29.599855 -0.04121512 0.7183433
    3    mpg~hp 30.098861 -0.06822828 0.6024373
    4  mpg~drat -7.524618  7.67823260 0.4639952
    5    mpg~wt 37.285126 -5.34447157 0.7528328
    6  mpg~qsec -5.114038  1.41212484 0.1752963
    7    mpg~vs 16.616667  7.94047619 0.4409477
    8    mpg~am 17.147368  7.24493927 0.3597989
    9  mpg~gear  5.623333  3.92333333 0.2306734
    10 mpg~carb 25.872334 -2.05571870 0.3035184
    

    seq_along(res.models) 而不仅仅是res.models 的原因是,我们还可以在列表中获取相关插槽的名称并将其放入您正在制作的数据框中。

    【讨论】:

    • 不错!如果您使用Map,您可以将名称作为第二个变量传递并避免索引。
    • 这很好,很干净,正是我要找的@ulfelder。这将创建一个dataframes 列表,此函数中是否有一种快速方法可以将数据帧列表写入一个 .csv?
    • 不,如果您想将整个表格放在一个 .csv 中,则必须在创建单个表格的 do.call 部分之后执行此操作。
    猜你喜欢
    • 1970-01-01
    • 2017-01-12
    • 2016-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多