使用不同公式的 dplyr 分组回归

Grouped regression with dplyr using different formulas

我尝试将问题从这个 post 转移到您在 lm() 中使用不同公式的设置 R 中的函数

这里是重现问题的基本设置:

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

# Generate data
set.seed(324)
dt <- data.frame(
  t = sort(rep(c(1,2), 50)),
  w1 = rnorm(100),
  w2 = rnorm(100),
  x1 = rnorm(100),
  x2 = rnorm(100)
)

# Generate formulas
fm <- map(1:2, ~as.formula(paste0("w", .x,  "~ x", .x)))

现在我尝试 运行 每个组的不同回归 t 使用公式对象 fm 中指定的模型:

# Approach 1:
dt %>% group_by(t) %>% 
  do(fit = tidy(map(fm, ~lm(.x, data = .)))) %>% 
  unnest(fit) 

# Approach 2
dt %>% nest(-t) %>% 
  mutate(
    fit = map(fm, ~lm(.x, data = .)),
    tfit = tidy(fit)
  )

这会产生一个错误,指示无法将公式转换为 data.frame。我做错了什么?

这需要 map2 而不是 map,因为 nestdata 列也是 data.framelist,因此我们需要遍历 'fm' listdata 的相应元素(map2 就是这样做的)

library(tidyr)
library(purrr)
library(dplyr)
library(broom)
out <- dt %>%
  nest(data = -t)  %>%
  mutate(
    fit = map2(fm, data, ~lm(.x, data = .y)), 
    tfit = map(fit, tidy))

-输出

> out
# A tibble: 2 × 4
      t data              fit    tfit            
  <dbl> <list>            <list> <list>          
1     1 <tibble [50 × 4]> <lm>   <tibble [2 × 5]>
2     2 <tibble [50 × 4]> <lm>   <tibble [2 × 5]>

> bind_rows(out$tfit)
# A tibble: 4 × 5
  term        estimate std.error statistic p.value
  <chr>          <dbl>     <dbl>     <dbl>   <dbl>
1 (Intercept)  0.0860      0.128    0.670   0.506 
2 x1           0.262       0.119    2.19    0.0331
3 (Intercept) -0.00285     0.152   -0.0187  0.985 
4 x2          -0.115       0.154   -0.746   0.459 

或者也可以使用

> imap_dfr(fm, ~ lm(.x, data = dt %>% 
                          filter(t == .y)) %>% 
               tidy)
# A tibble: 4 × 5
  term        estimate std.error statistic p.value
  <chr>          <dbl>     <dbl>     <dbl>   <dbl>
1 (Intercept)  0.0860      0.128    0.670   0.506 
2 x1           0.262       0.119    2.19    0.0331
3 (Intercept) -0.00285     0.152   -0.0187  0.985 
4 x2          -0.115       0.154   -0.746   0.459 

如果我们想要't'的每个级别都有'fm'的所有组合,那么使用crossing

dt %>% 
   nest(data = -t) %>% 
   crossing(fm) %>% 
   mutate(fit = map2(fm, data, ~ lm(.x, data = .y)),
        tfit = map(fit, tidy))

-输出

# A tibble: 4 × 5
      t data              fm        fit    tfit            
  <dbl> <list>            <list>    <list> <list>          
1     1 <tibble [50 × 4]> <formula> <lm>   <tibble [2 × 5]>
2     1 <tibble [50 × 4]> <formula> <lm>   <tibble [2 × 5]>
3     2 <tibble [50 × 4]> <formula> <lm>   <tibble [2 × 5]>
4     2 <tibble [50 × 4]> <formula> <lm>   <tibble [2 × 5]>