Передать функцию с параметрами аргументу функции в r

Я изо всех сил пытаюсь понять все нюансы при передаче чего-либо функции в R. Пакет rlang и то, как его использовать, сбивают меня с толку. Не могу найти хорошего руководства, когда использовать все различные rlang :: sym или связанные с ним функции.

В любом случае, я пытаюсь создать функцию, которая позволяет передавать пользовательскую функцию и связанные с ней параметры. Например, означает, квантили и т. Д. Я хочу, чтобы user_metric всегда был в кавычках, а также он должен иметь возможность содержать различные аргументы, такие как na.rm = TRUE и т. Д. Может ли кто-нибудь показать мне, как это может работать, поэтому, хочу ли я передать «среднее» или «среднее (., 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')

person runningbirds    schedule 25.10.2018    source источник
comment
Во-первых, в этом коде есть несбалансированные круглые скобки. Получите себе редактор с поддержкой синтаксиса, который можно найти во многих IDE.   -  person IRTFM    schedule 25.10.2018


Ответы (1)


Вы должны отличать ваш первый случай, когда вы просто указываете имя функции, от других случаев, когда вы фактически определяете лямбда-функцию. В первом случае вы можете использовать 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.

person Artem Sokolov    schedule 26.10.2018