2

我正在尝试创建一个将列名列表传递给函数的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)

如何让列表中的项目单独引用?

这个问题类似于Passing dataframe column names in a function inside another function但在评论中建议使用字符串,而在这里我想使用裸列名。

4

2 回答 2

4
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' 的平均值。此外,您也可以通过传入函数来概括它。

于 2017-12-27T16:55:29.347 回答
1

您可以使用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而不是listthis answer所示,这完全绕过了一些复杂性。

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
于 2017-12-27T15:42:44.527 回答