将带有参数的函数传递给 r 中的函数参数
Pass in function with parameters to function arguement in r
我很难理解将某些东西传递给 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')
您必须区分第一种情况(您只需提供函数名称)和其他情况(您有效定义 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
两边都是可选的。
我很难理解将某些东西传递给 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')
您必须区分第一种情况(您只需提供函数名称)和其他情况(您有效定义 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
两边都是可选的。