(整洁,一目了然,增加)与 exec
(tidy, glance, augment) with exec
我从 purrr
文档中看到,应该可以使用 map(list(fn1, fn2, fn3), exec, !!!args)
语法或类似的语法将函数列表映射到参数。对于 broom
函数 tidy
、glance
和 augment
,通常必须用 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
我从 purrr
文档中看到,应该可以使用 map(list(fn1, fn2, fn3), exec, !!!args)
语法或类似的语法将函数列表映射到参数。对于 broom
函数 tidy
、glance
和 augment
,通常必须用 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