在将某些内容传递给R中的函数时,我很难理解所有的细微差别。rlang包及其使用方法使我感到困惑。在何时使用所有各种rlang :: sym或相关功能方面找不到很好的指南。
无论如何,我正在尝试制作一个允许传入用户定义的函数和相关参数的函数。例如均值,分位数等。我希望user_metric始终用引号引起来,并且它还必须能够包含各种参数本身,例如na.rm = TRUE等。有人可以告诉我这是怎么工作的,所以无论我要传递'mean'还是'mean(。,na.rm = TRUE)'都可以?
library(tidyverse)
group_by_metrics=function(data, group_col, user_metric){
metrics = data %>% group_by(!!rlang:sym(group_col)) %>% summarise_all(.funs = funs(!!rlang::syms(user_metric))
return(metrics)
}
group_by_metrics(data=mtcars, group_col='vs', user_metric='mean')
group_by_metrics(data=mtcars, group_col='vs', user_metric='mean(., na.rm = TRUE)'
group_by_metrics(data=mtcars, group_col='vs', user_metric ='quantile(., probs=0.95, na.rm = TRUE')
答案 0 :(得分:1)
您必须区分仅提供函数名称的第一种情况与有效定义lambda函数的其他情况。对于前者,可以使用match.fun
通过名称查找函数。对于后者,将您的字符串转换为公式,然后使用purrr::as_mapper()
来使它们成为函数。使用ensym
而不是sym
允许使用不带引号的参数。
group_by_metrics <- function(.data, group_col, user_metric)
{
f <- purrr::possibly( match.fun, NULL )(user_metric)
if( is.null(f) )
f <- str_c( "~", user_metric ) %>% as.formula %>% as_mapper
.data %>% group_by(!!rlang::ensym(group_col)) %>% summarize_all( f )
}
group_by_metrics( mtcars, "vs", "quantile(., probs=0.95, na.rm=TRUE)" )
# vs mpg cyl disp hp drat wt qsec am gear carb
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 21.7 8 462. 275. 4.25 5.36 18.0 1 5 6.30
# 2 1 32.9 6 237. 123 4.47 3.45 21.2 1 4.35 4
## Using ensym instead of sym allows you to drop " for group_col
group_by_metrics( mtcars, vs, "mean" )
# vs mpg cyl disp hp drat wt qsec am gear carb
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 16.6 7.44 307. 190. 3.39 3.69 16.7 0.333 3.56 3.61
# 2 1 24.6 4.57 132. 91.4 3.86 2.61 19.3 0.5 3.86 1.79
请注意,如果您使用...
分别传递其他参数,则可以避免所有这种转换:
group_by_metrics2 <- function(.data, group_col, user_metrics, ...)
{
.data %>% group_by(!!rlang::ensym(group_col)) %>%
summarize_all( user_metrics, ... )
}
group_by_metrics2( mtcars, "vs", "quantile", probs=0.05, na.rm=TRUE)
# # A tibble: 2 x 11
# vs mpg cyl disp hp drat wt qsec am gear carb
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 10.4 5.7 141. 107. 2.90 2.55 14.6 0 3 2
# 2 1 18.0 4 74.1 58.5 2.97 1.58 17.8 0 3 1
在最后一个示例中,"
和vs
周围的字符串引号quantile
是可选的。