如何在dplyr 0.7中参数化函数调用?

如何在dplyr 0.7中参数化函数调用?,r,dplyr,rlang,R,Dplyr,Rlang,dplyr 0.7的发行版包括一系列使用dplyr编程的功能。我仔细阅读了本文档,并试图了解它将如何影响我对dplyr的使用 以下是我在使用dplyr构建报告和聚合函数时使用的常用习惯用法: my_report <- function(data, grouping_vars) { data %>% group_by_(.dots=grouping_vars) %>% summarize(x_mean=mean(x), x_median=median(x),

dplyr 0.7的发行版包括一系列使用dplyr编程的功能。我仔细阅读了本文档,并试图了解它将如何影响我对dplyr的使用

以下是我在使用dplyr构建报告和聚合函数时使用的常用习惯用法:

my_report <- function(data, grouping_vars) {
  data %>%
    group_by_(.dots=grouping_vars) %>%
    summarize(x_mean=mean(x), x_median=median(x), ...)
}

如果您想按可能不止一列进行分组,可以使用
quos

grouping_vars <- quos(am, gear)
mtcars %>%
  group_by(!!!grouping_vars) %>%
  summarise(mean_cyl=mean(cyl))
#      am  gear mean_cyl
#   <dbl> <dbl>    <dbl>
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000
分组变量%
分组依据(!!!分组变量)%>%
总结(平均值=平均值)
#am档位平均值
#        
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000
现在,似乎没有一个很好的方法把弦变成曲子。但有一种方法确实有效

cols <- c("am","gear")
grouping_vars <- rlang::parse_quosures(paste(cols, collapse=";"))
mtcars %>%
  group_by(!!!grouping_vars) %>%
  summarise(mean_cyl=mean(cyl))
#      am  gear mean_cyl
#   <dbl> <dbl>    <dbl>
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000
cols%
总结(平均值=平均值)
#am档位平均值
#        
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000

dplyr
将在处有一个专门的group by function
group by,用于处理多个分组变量。在
系列中使用
\u的新成员会容易得多:

# using the pre-release 0.6.0

cols <- c("am","gear")

mtcars %>%
    group_by_at(.vars = cols) %>%
    summarise(mean_cyl=mean(cyl))

# Source: local data frame [4 x 3]
# Groups: am [?]
# 
# am  gear mean_cyl
# <dbl> <dbl>    <dbl>
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000
#使用预发行版0.6.0
科尔斯%
分组单位:(.vars=cols)%>%
总结(平均值=平均值)
#来源:本地数据帧[4 x 3]
#组:am[?]
# 
#am档位平均值
#      
# 1     0     3 7.466667
# 2     0     4 5.000000
# 3     1     4 4.500000
# 4     1     5 6.000000
.vars
参数接受由
vars
生成的字符/数字向量或列名:

瓦尔斯先生

由vars()生成的列列表,或 列名,或列位置的数字向量


这是我为自己写的快速而肮脏的参考资料

# install.packages("rlang")
library(tidyverse)

dat <- data.frame(cat = sample(LETTERS[1:2], 50, replace = TRUE),
                  cat2 = sample(LETTERS[3:4], 50, replace = TRUE),
                  value = rnorm(50))
如果您使用
dplyr
函数之外,您将得到一个错误

在函数内部,
rlang::sym
rlang::syms
的用法是相同的

summarize_by <- function(df, summ_var, group_vars) {

  summ_sym <- rlang::sym(summ_var)
  group_syms <- rlang::syms(group_vars)

  df %>%
    group_by(!!!group_syms) %>%
    summarize(summ = sum(!!summ_sym))
}
对列/变量名使用非标准求值 然后我们的函数调用是

summarize_by(dat, value, cat, cat2)

如果您提供了可用于测试可能的解决方案的示例输入数据,则更容易提供帮助。@MrFlick我刚刚尝试设置了一个示例,但在这个过程中,我发现我甚至无法让基于quosure的示例工作。所以我提交了一个github问题,得到了回复并相应地更新了我的帖子。@joran在我这方面,你没有
rlang::parse_quosures
的版本会生成一个只有
am
,而不是
am
gear
的groupby。这对你来说有什么不同吗?@Paul或我只是希望
rlang::parse_quosures
可以采用一个合适的向量,而不必折叠。如果没有一个好的便利功能,我会感到惊讶forthcoming@Paul事实上,当我在思考这个问题时,我只是在想,这个新方法似乎非常适合编写以裸列名为参数的函数。奇怪的是,我更关注于编写交互式函数,而不是一般的函数。我喜欢旧的dplyr函数,因为它们将NSE版本转换为SE版本,这更易于使用/编程。这个新版本似乎完全是非标准的疯狂。@Paul我对我的答案非常恼火,所以我也这么做了:切换我的复选标记,因为这看起来将是前进的标准方式。
summarize_by <- function(df, summ_var, group_vars) {

  summ_sym <- rlang::sym(summ_var)
  group_syms <- rlang::syms(group_vars)

  df %>%
    group_by(!!!group_syms) %>%
    summarize(summ = sum(!!summ_sym))
}
summarize_by(dat, "value", c("cat", "cat2"))
summ_quo <- quo(value)  # capture a single variable for NSE
group_quos <- quos(cat, cat2)  # capture list of variables for NSE

dat %>%
  group_by(!!!group_quos) %>%  # use !!! with both quos and rlang::syms
  summarize(summ = sum(!!summ_quo))  # use !! both quo and rlang::sym
summarize_by <- function(df, summ_var, ...) {

  summ_quo <- enquo(summ_var)  # can only capture a single value!
  group_quos <- quos(...)  # captures multiple values, also inside functions!?

  df %>%
    group_by(!!!group_quos) %>%
    summarize(summ = sum(!!summ_quo))
}
summarize_by(dat, value, cat, cat2)