(整洁,一目了然,增加)与 exec

(tidy, glance, augment) with exec

我从 purrr 文档中看到,应该可以使用 map(list(fn1, fn2, fn3), exec, !!!args) 语法或类似的语法将函数列表映射到参数。对于 broom 函数 tidyglanceaugment,通常必须用 do 进行补充,这将如何工作?这三个函数我几乎总是喜欢在相同的数据和模型上同时执行。当然我可以明确地这样做:

# works but is repetitive
MY_MODEL <- hp ~ cyl
my_glance <- mtcars %>% do(glance(lm(data = ., formula = MY_MODEL)))
my_tidy <- mtcars %>% do(tidy(lm(data = ., formula = MY_MODEL)))
my_augment <- mtcars %>% do(augment(lm(data = ., formula = MY_MODEL)))

我怀疑有更好、更紧凑的方法可以做到这一点,而不必每次都重新输入 ...lm(data = ., formula = MY_MODEL...,但我想不出来。我试过了

# doesn't work
omnibroom <- function(df, model){
    map(list(glance, tidy, augment),
        exec,
        ~{(do(.x(lm(data = df, formula = model))))}
        )
    }

omnibroom(mtcars, MY_MODEL)

但我认为我没有正确理解 !!! 语法。

在同一个模型和数据上调用这三个扫帚函数有没有紧凑的习惯用法

可以通过简单的重构在两行中完成此操作。不需要 do!!!

mdl <- mtcars %>% lm(data=., formula=MY_MODEL)
res1 <- map( list(glance, tidy, augment), exec, mdl )

如果您真的想将其压缩成一行,请使用 { 帮助将管道输入引导到 lm 中的正确位置:

res2 <- mtcars %>% 
    {map( list(glance, tidy, augment), exec, lm(data=., formula=MY_MODEL) )}

验证:

identical( res1, list(my_glance, my_tidy, my_augment) )    # TRUE
identical( res1, res2 )                                    # TRUE

编辑地址分组

lm这样的任意函数不考虑数据帧组。虽然在这种情况下 do 是处理分组的一种流行方法,但我个人认为 tidyr::nest() 更直观,因为它将所有中间值和结果放在数据旁边:

## "Listify" broom functions: f -> map( ..., f )
omnibroom <- map( list(glance, tidy, augment), ~function(l) map(l, .x) ) %>%
    set_names( c("glance","tidy","augment") )

result <- mtcars %>% nest( data = -gear ) %>%
    mutate( model = map(data, lm, formula=MY_MODEL) ) %>%
    mutate_at( "model", omnibroom )

#  # A tibble: 3 x 6
#     gear data              model  glance           tidy           augment
#    <dbl> <list>            <list> <list>           <list>         <list>
#  1     4 <tibble [12 × 10… <lm>   <tibble [1 × 11… <tibble [2 × … <tibble [12 × …
#  2     3 <tibble [15 × 10… <lm>   <tibble [1 × 11… <tibble [2 × … <tibble [15 × …
#  3     5 <tibble [5 × 10]> <lm>   <tibble [1 × 11… <tibble [2 × … <tibble [5 × 9…

这种格式自然也适合取消嵌套,因为 broom 函数会生成数据帧:

result %>% select( gear, tidy ) %>% unnest( tidy )

#  # A tibble: 6 x 6
#     gear term        estimate std.error statistic p.value
#    <dbl> <chr>          <dbl>     <dbl>     <dbl>   <dbl>
#  1     4 (Intercept)    -5.00     25.3     -0.198 0.847
#  2     4 cyl            20.2       5.30     3.82  0.00339
#  3     3 (Intercept)   -47.5      56.1     -0.847 0.412
#  4     3 cyl            30.0       7.42     4.04  0.00142
#  5     5 (Intercept)  -101.       51.9     -1.94  0.148
#  6     5 cyl            49.4       8.28     5.96  0.00944