免责声明:虽然mutate_at
@aosmith 提出的解决方案在我看来是最好和最简单的解决方案,但我认为看看如何使用rlang
工具来解决问题(如果mutate_at
不存在)可能是有益的。为了科学!
如评论中所述,您将需要purrr::map()
研究功能系列。您还将遇到一个单独的问题,!!!mean_names := mean(!!!exprs)
因为!!!
拼接运算符不能用于赋值的左侧。
最好的rlang
方法是将mutate
表达式组成一个命名列表。用于quo
执行表达式算术和stringr::str_c
(或paste0
你一直在做的)字符串算术:
library( tidyverse )
my_mutate <- function(df, ...) {
exprs <- enquos(...)
mean_exprs <- set_names(
map(exprs, ~quo(mean(!!.x))), # mpg becomes mean(mpg)
str_c("mean_", map_chr(exprs, quo_name)) ) # mpg becomes "mean_mpg"
sum_exprs <- set_names(
map(exprs, ~quo(sum(!!.x))), # mpg becomes sum(mpg)
str_c("sum_", map_chr(exprs, quo_name)) ) # mpg becomes "sum_mpg"
mutate(df, !!!mean_exprs, !!!sum_exprs)
}
mtcars %>% my_mutate( mpg, cyl )
# mpg cyl disp hp ... mean_mpg mean_cyl sum_mpg sum_cyl
# 1 21.0 6 160 110 ... 20.09062 6.1875 642.9 198
# 2 21.0 6 160 110 ... 20.09062 6.1875 642.9 198
# 3 22.8 4 108 93 ... 20.09062 6.1875 642.9 198
# 4 21.4 6 258 110 ... 20.09062 6.1875 642.9 198
奖励:您会注意到我们在上面的表达式定义中重复了一大段代码。我们可以将其提取到一个独立的函数中,该函数使用提供的函数自动构造表达式并相应地命名这些表达式:
mutator <- function(f, ...) {
f_expr <- enquo(f)
exprs <- enquos(...)
## Same code as in my_mutate above, but with an arbitrary function
set_names(
map( exprs, ~quo((!!f_expr)(!!.x)) ),
str_c( quo_name(f_expr), "_", map_chr(exprs, quo_name) )
)
}
## Example usage
mutator( sd, mpg, cyl )
# $sd_mpg
# <quosure>
# expr: ^^sd(^mpg)
# env: 0x555e05260020
# $sd_cyl
# <quosure>
# expr: ^^sd(^cyl)
# env: 0x555e05273af8
我们现在可以使用新mutator
函数重新定义my_mutate
为一个简单的单线:
my_mutate2 <- function(df, ...) {
mutate( df, !!!mutator(mean, ...), !!!mutator(sum, ...) )
}