运行 跨多个变量的单一线性回归,分组

Running single linear regressions across multiple variables, in groups

我正在尝试 运行 对大量变量进行简单的单一线性回归,根据另一个变量分组。以 mtcars 数据集为例,我想 运行 mpg 和每个其他变量(mpg ~ disp、mpg ~ hp 等)之间的单独线性回归,由另一个变量分组(例如,cyl ).

运行 可以使用 purrr::map 轻松完成每个变量的 lm(从这个很棒的教程 - https://sebastiansauer.github.io/EDIT-multiple_lm_purrr_EDIT/ 修改):

library(dplyr)
library(tidyr)
library(purrr)

mtcars %>%
  select(-mpg) %>% #exclude outcome, leave predictors
  map(~ lm(mtcars$mpg ~ .x, data = mtcars)) %>%
  map_df(glance, .id='variable') %>%
  select(variable, r.squared, p.value)

# A tibble: 10 x 3
   variable r.squared  p.value
   <chr>        <dbl>    <dbl>
 1 cyl          0.726 6.11e-10
 2 disp         0.718 9.38e-10
 3 hp           0.602 1.79e- 7
 4 drat         0.464 1.78e- 5
 5 wt           0.753 1.29e-10
 6 qsec         0.175 1.71e- 2
 7 vs           0.441 3.42e- 5
 8 am           0.360 2.85e- 4
 9 gear         0.231 5.40e- 3
10 carb         0.304 1.08e- 3

并且 运行在分组变量上建立线性模型也很容易使用 map:

mtcars %>%
  split(.$cyl) %>% #split by grouping variable
  map(~ lm(mpg ~ wt, data = .)) %>%
  map_df(broom::glance, .id='cyl') %>%
  select(cyl, variable, r.squared, p.value)

# A tibble: 3 x 3
  cyl   r.squared p.value
  <chr>     <dbl>   <dbl>
1 4         0.509  0.0137
2 6         0.465  0.0918
3 8         0.423  0.0118

所以我可以 运行 按变量或按组。但是,我无法弄清楚如何将这两者结合起来(按 cyl 对所有内容进行分组,然后 运行ning lm(mpg ~ 每个其他变量,分别)。我希望做这样的事情:

mtcars %>%
  select(-mpg) %>% #exclude outcome, leave predictors
  split(.$cyl) %>% # group by grouping variable
  map(~ lm(mtcars$mpg ~ .x, data = mtcars)) %>% #run lm across all variables
  map_df(glance, .id='cyl') %>%
  select(cyl, variable, r.squared, p.value)

并得到一个结果,给我 cyl(group)、变量、r.squared 和 p.value(3 组 * 10 个变量的组合 = 30 个模型输出)。

但是 split() 将数据帧转换为列表,这是第 1 部分 [ map(~ lm(mtcars$mpg ~ .x, data = mtcars)) ] 无法处理。我试图修改它,使其不明确引用原始数据结构,但无法找到可行的解决方案。非常感谢任何帮助!

IIUC,你可以使用 group_bygroup_modify,里面有一个 map 来迭代预测变量。

如果您可以提前隔离预测变量,就会变得更容易,就像此解决方案中的 ivs 一样。

library(tidyverse)

ivs <- colnames(mtcars)[3:ncol(mtcars)]
names(ivs) <- ivs

mtcars %>% 
  group_by(cyl) %>% 
  group_modify(function(data, key) {
    map_df(ivs, function(iv) {
      frml <- as.formula(paste("mpg", "~", iv))
      lm(frml, data = data) %>% broom::glance()
      }, .id = "iv") 
  }) %>% 
  select(cyl, iv, r.squared, p.value)

# A tibble: 27 × 4
# Groups:   cyl [3]
     cyl iv    r.squared  p.value
   <dbl> <chr>     <dbl>    <dbl>
 1     4 disp  0.648      0.00278
 2     4 hp    0.274      0.0984 
 3     4 drat  0.180      0.193  
 4     4 wt    0.509      0.0137 
 5     4 qsec  0.0557     0.485  
 6     4 vs    0.00238    0.887  
 7     4 am    0.287      0.0892 
 8     4 gear  0.115      0.308  
 9     4 carb  0.0378     0.567  
10     6 disp  0.0106     0.826  
11     6 hp    0.0161     0.786  
# ...