【问题标题】:R adding regression coeffcients to data frameR将回归系数添加到数据框
【发布时间】:2015-06-30 16:19:07
【问题描述】:

我有一个数据框列表,其中包含许多数据子集(470ish)。我正在尝试对它们中的每一个进行回归并将回归系数添加到数据框中。数据框将包含每个子组上所有因变量的系数。我尝试使用 for 循环进行迭代,但显然这不是正确的方法。我认为解决方案与 lapply 有关?

for (i in ListOfTraining){


    lm(JOB_VOLUME ~  FEB+MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC        data=ListOfTraining[[i]])

}

感谢您的建议!

【问题讨论】:

    标签: r lapply


    【解决方案1】:

    broom 包中的函数 tidy 可以很好地处理这个问题。

    library(dplyr)          # bind_rows is more efficient than do.call(rbind, ...)
    library(broom)          # put statistics into data.frame
    bind_rows(lapply(ListOfTraining, function(dat)
        tidy(lm(JOB_VOLUME ~ FEB+MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC, data=dat))))
    

    例子

    dataList <- split(mtcars, mtcars$cyl)  # list of data.frames by number of cylinders
    lapply(dataList, function(dat) tidy(lm(mpg ~ disp + hp, data=dat))) %>%  # fit models
      bind_rows() %>%                                                        # combine into one data.frame
      mutate(model=rep(1:length(dataList), each=3))                          # add a model ID column
    #          term     estimate   std.error   statistic      p.value model
    # 1 (Intercept) 43.040057552 4.235724713 10.16120274 7.531962e-06     1
    # 2        disp -0.119536016 0.036945788 -3.23544366 1.195900e-02     1
    # 3          hp -0.046091563 0.047423668 -0.97191054 3.595602e-01     1
    # 4 (Intercept) 20.151209478 6.938235241  2.90437104 4.392508e-02     2
    # 5        disp  0.001796527 0.020195109  0.08895852 9.333909e-01     2
    # 6          hp -0.006032441 0.034597750 -0.17435935 8.700522e-01     2
    # 7 (Intercept) 24.044775630 4.045729006  5.94324919 9.686231e-05     3
    # 8        disp -0.018627566 0.009456903 -1.96973225 7.456584e-02     3
    # 9          hp -0.011315585 0.012572498 -0.90002676 3.873854e-01     3
    

    或者,您可以预先绑定 data.frames,假设它们具有相同的列。然后,使用 nlme 包中的 lmList 拟合模型。

    ## Combine list of data.frames into one data.frame with a factor variable
    lengths <- sapply(dataList, nrow)  # in case data.frames have different num. rows
    dat <- dataList %>% bind_rows() %>% 
      mutate(group=rep(1:length(dataList), times=lengths))  # group id column
    
    library(nlme)  # lmList()
    models <- lmList(mpg ~ disp + hp | group, data=dat)  # make models, grouped by group
    models$coefficients
    #   (Intercept)         disp           hp
    # 1    43.04006 -0.119536016 -0.046091563
    # 2    20.15121  0.001796527 -0.006032441
    # 3    24.04478 -0.018627566 -0.011315585
    

    【讨论】:

    • 您可以从列表的最后一行中提取 data.frames 的名称,而不是任意模型 #s:mutate(model=rep(names(dataList), each=3))
    • @SamFirke 好主意,我希望bind_rows 有办法自动创建一个 id 列,但似乎还没有实现
    • 希望添加功能。看起来至少在讨论中:github.com/hadley/dplyr/pull/825
    【解决方案2】:

    如果您愿意,可以使用for 循环来解决此问题。您的问题是随着循环的进行,结果没有保存到对象中。您可以在下面查看使用内置 mtcars 数据框的示例。

    (第一个示例是根据 OP 对如何提取 R 平方值的示例的请求进行修改的。)

    ListOfTraining <- list(mtcars, mtcars)
    results <- list()
    
    for (i in seq_along(ListOfTraining)) {
      lm_obj <- lm(disp ~ qsec, data = ListOfTraining[[i]])
      tmp <- c(lm_obj$coefficients, summary(lm_obj)$r.squared)
      names(tmp)[length(tmp)] <- "r.squared"
      results[[i]] <- tmp
    }
    
    results <- do.call(rbind, results)
    results
    

    您还可以使用lapply 重写for 循环,如下所示。

    ListOfTraining <- list(mtcars, mtcars)
    results <- list()
    
    results <- lapply(ListOfTraining, function(x) {
      lm(disp ~ qsec, data = x)$coefficients
    })
    
    results <- do.call(rbind, results)
    results
    

    最后,您可以使用plyr 包的ldply 函数,它会自动将列表应用的输出转换为数据框(如果可能的话)。

    ListOfTraining <- list(mtcars, mtcars)
    results <- plyr::ldply(ListOfTraining, function(x) {
      lm(disp ~ qsec, data = x)$coefficients
    })
    results
    

    【讨论】:

    • 非常感谢。我使用了 for 循环,它工作得很好。如果我想将 r 平方值作为一列添加到具有所有系数的新数据框中,我将如何做呢?谢谢!
    【解决方案3】:

    您当前的代码运行回归,但不对结果做任何事情(在循环内它们甚至不会自动打印),因此它们只是被丢弃。你需要有一些结构来保存结果。

    以下代码将创建一个系数矩阵(假设所有回归都运行无误且最终系数的数量相同):

    my.coef <- sapply( ListOfTraining, function(dat) { 
        coef(lm( JOB_VOLUME ~ FEB+MAR+APR+MAY+JUN+JUL+AUG+SEP+OCT+NOV+DEC,
                 data=dat) )
    })
    

    然后可以将矩阵转换为数据框(您也可以使用lapply 并转换为数据框,但我认为sapply 选项可能更简单一些)。

    【讨论】:

      猜你喜欢
      • 2019-09-28
      • 2020-10-19
      • 1970-01-01
      • 2020-08-02
      • 1970-01-01
      • 2017-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多