Tidyeval со списком имен столбцов в функции

Я пытаюсь создать функцию, которая передает список имен столбцов в dplyr функция. Я знаю, как это сделать, если список имен столбцов приведен в ... форма, как объяснено в tidyeval документация:

df <- tibble(
  g1 = c(1, 1, 2, 2, 2),
  g2 = c(1, 2, 1, 2, 1),
  a = sample(5), 
  b = sample(5)
)

my_summarise <- function(df, ...) {
  group_var <- quos(...)

  df %>%
    group_by(!!!group_var) %>%
    summarise(a = mean(a))
}

my_summarise(df, g1, g2)

Но если я хочу перечислить имена столбцов в качестве аргумента функции, приведенное выше решение не будет работать (конечно):

my_summarise <- function(df, group_var, sum_var) {
  group_var <- quos(group_var) # nor enquo(group_var)
  sum_var <- enquo(sum_var)

  df %>%
    group_by(!!!group_var) %>%
    summarise(a = mean(a))
}

my_summarise(df, list(g1, g2), a)
my_summarise(df, list(g1, g2), b)

Как я могу получить элементы в списке для индивидуального цитирования?

Этот вопрос аналогичен передаче имен столбцов dataframe в функции внутри другой функции, но в комментариях было предложено использовать строки, в то время как здесь я хотел бы использовать голые имена столбцов.

2 ответа

Решение

Вы можете передать свой список аргументов, используя alist вместо list, поскольку это не будет оценивать аргументы.

my_summarise = function(df, group_var, sum_var) {
    group_var = quos(!!! group_var)
    sum_var = enquo(sum_var)

    df %>%
        group_by(!!! group_var) %>%
        summarise(!! quo_name( sum_var) := mean( !! sum_var) )
}

my_summarise(df, alist(g1, g2), b)

# A tibble: 4 x 3
# Groups:   g1 [?]
     g1    g2     b
  <dbl> <dbl> <dbl>
1     1     1   2.0
2     1     2   3.0
3     2     1   4.5
4     2     2   1.0

Другой альтернативой было бы передать этот аргумент непосредственно quos вместо list как показано в этом ответе, который обходит некоторые осложнения все вместе.

my_summarise = function(df, group_var, sum_var) {
    # group_var = quos(!!! group_var)
    sum_var = enquo(sum_var)

    df %>%
        group_by(!!! group_var) %>%
        summarise(!! quo_name( sum_var) := mean( !! sum_var) )
}

my_summarise(df, quos(g1, g2), b)

# A tibble: 4 x 3
# Groups:   g1 [?]
     g1    g2     b
  <dbl> <dbl> <dbl>
1     1     1   2.0
2     1     2   3.0
3     2     1   4.5
4     2     2   1.0
library(dplyr)

df <- tibble(
  g1 = c(1, 1, 2, 2, 2),
  g2 = c(1, 2, 1, 2, 1),
  a = sample(5), 
  b = sample(5)
)

my_summarise = function(df, group_var, fun_name) {

  df %>%
    group_by(!!! group_var) %>%
    summarize_all(fun_name)
}

my_summarise(df, alist(g1, g2), mean)

alist() обрабатывает аргументы 'g1' и 'g2' как аргументы функции (не оценивает их), в то время как!!! (Так же, как UQS(), заключает в кавычки и склеивает список. sum_var не является необходимым, так как похоже, что вы хотите получить среднее значение для "a" и "b". Кроме того, вы можете обобщить его, передав также функцию.

Другие вопросы по тегам