关注Programming with dplyr我注意到可以使用quo_name添加名称。我想知道如何为多列执行此操作,例如。像quos_name的种类。 E.g:
my_mutate <- function(df, expr) {
expr <- enquo(expr)
mean_name <- paste0("mean_", quo_name(expr))
sum_name <- paste0("sum_", quo_name(expr))
mutate(df,
!!mean_name := mean(!!expr),
!!sum_name := sum(!!expr)
)
}
成为
my_mutate <- function(df, ...) {
exprs <-quos(...)
mean_names <- paste0("mean_", quos_name(exprs))
sum_names <- paste0("sum_", quos_name(exprs))
mutate(df,
!!!mean_names := mean(!!!exprs),
!!!sum_names := sum(!!!exprs)
)
}
即。为...中指定的所有列添加mean和sum列 当然这只是一个例子,quos_names不存在。如果有办法,这将是非常有帮助的。
我知道可以在data.table DT[,(Col_names):=lapply(Cols,mean)]
中执行类似这样的操作(此代码不起作用,但之前我做过类似的事情)。
答案 0 :(得分:2)
免责声明:虽然我认为@aosmith提出的mutate_at
是最好,最简单的解决方案,但我认为了解如何使用{{1 }}工具,如果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
答案 1 :(得分:0)
您似乎找到了使用mutate_at
的答案,但如果您需要在其他情境中执行此操作,我将添加以下方式。
如果您使用以下功能,您将看到quos(...)
返回与您的参数对应的状态列表。
watch_quos <- function(...){
quos_args <- quos(...)
return(quos_args)
}
# Returns a list of closures
watch_quos(hello, iam, several, arguments)
因此,您可以使用quos
或quo_name
中的一个轻松将sapply
的结果转换为将lapply
应用于每个引用参数的字符列表(或矢量):
quo_names <- function(...) {
quos_args <- quos(...)
char_args <- lapply(quos_args, quo_name)
return(char_args)
}
# Returns a character list
quo_names(hello, iwill, be, char, arguments)