问题描述
在使用dplyr编程之后,我注意到一个人可以使用quo_name添加名称.我想知道如何对多个列执行此操作,例如.就像各种各样的quos_name一样.例如:
Hi following Programming with dplyr I noticed that one can add a name using quo_name. I was wondering how to do this for multiple columns, eg. like a quos_name of sorts. 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)
)
}
即.为...中指定的所有列添加均值和求和列,当然这仅是一个示例,quos_names不存在.如果有办法的话,这将非常有帮助.
ie. adding the mean and sum columns for all columns specified in ..., of course this is only as an example and quos_names don't exist. It would be very helpful if there is a way of doing this.
例如,我知道可以在data.table DT[,(Col_names):=lapply(Cols,mean)]
中执行类似的操作(此代码不起作用,但是我之前已经执行过类似的操作).
I know it is possible to do something like this in data.table DT[,(Col_names):=lapply(Cols,mean)]
for instance (This code does not work, but I have done something like this before).
推荐答案
免责声明:虽然我认为@aosmith提出的mutate_at
是最好,最简单的解决方案,但我认为这可能是有启发性的了解如果mutate_at
不存在,如何使用rlang
工具解决该问题.为了科学!
DISCLAIMER: While mutate_at
proposed by @aosmith is in my opinion the best and simplest solution, I think it might be instructive to see how the problem could be approached using rlang
tools, if mutate_at
didn't exist. For science!
如评论中所述,您将需要研究purrr::map()
系列功能.您还会遇到!!!mean_names := mean(!!!exprs)
的另一个问题,因为!!!
拼接运算符不能在分配的左手使用.
As mentioned in the comments, you will want to look into purrr::map()
family of functions. You will also run into a separate problem with !!!mean_names := mean(!!!exprs)
because the !!!
splice operator cannot be used on the left hand of the assignment.
最好的rlang
方法是将mutate
表达式组成一个命名列表.使用quo
执行表达式算术,并使用stringr::str_c
(或一直在执行paste0
)进行字符串算术:
The best rlang
approach is to compose your mutate
expressions as a named list. Use quo
to perform expression arithmetic and stringr::str_c
(or paste0
as you've been doing) for string arithmetic:
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
奖金::您会注意到我们在上面的表达式定义中重复了一段代码.我们可以将其提取到一个独立的函数中,该函数使用所提供的函数自动构造表达式并相应地命名这些表达式:
BONUS: You will notice that we are repeating a chunk of code in our definition of expressions above. We can pull that out into a standalone function that automatically constructs expressions with the provided function and names those expressions accordingly:
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
重新定义为简单的单行代码:
We can now use the new mutator
function to re-define my_mutate
as a simple one-liner:
my_mutate2 <- function(df, ...) {
mutate( df, !!!mutator(mean, ...), !!!mutator(sum, ...) )
}
这篇关于R quo_name等同于quos的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!