4

我想编写使用 dplyr 动词的函数,这意味着我必须涉足rlang.

举一个具体的例子,假设我想用来purrr::map_df()迭代 a 中的变量dplyr::group_by()。用dplyr vignette编程遍历编写my_summarise()函数;该方法是rlang::enquo()在分组变量上使用,然后用. 取消引用!!。这种方法可以创建一个新的类似 dplyr 的函数,该函数采用不带引号的变量名称(my_summarise(df, g1)在小插图中)。

相反,我想将变量名作为字符串提供。这rlang::sym()是正确的方法吗?似乎不是,因为sym()在 dplyr 编程小插图中没有提到,在 rlang tidy 评估文章中也几乎没有提到。有没有更好的办法?

library(tidyverse)
my_summarise <- function(df, group_var) {
  group_var <- rlang::sym(group_var)

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

# This works. Is that a good thing?
purrr::map_df(c("cyl", "am"), my_summarise, df = mtcars)

# A tibble: 5 x 3
    cyl   mpg    am
  <dbl> <dbl> <dbl>
1  4.00  26.7 NA   
2  6.00  19.7 NA   
3  8.00  15.1 NA   
4 NA     17.1  0   
5 NA     24.4  1.00

作为后续,为什么有时简单地取消引用(没有首先应用enquoor sym)会起作用?在下面的示例中,为什么select()按预期工作但group_by()没有?

x <- "cyl"
select(mtcars, !!x)
group_by(mtcars, !!x)

更新:答案不是取消引用。它select更灵活,可以处理字符串,而group_by不能。

其他参考:Edwin Thoen 的这篇博文。

4

1 回答 1

3

简短的回答:是的。

如果你想map超过列,sym是一个很好的方法。莱昂内尔亨利sym草稿插图中演示。

如果您想传递列名,但不尝试迭代,Kirill Müller更喜欢 quo. 在下面的示例中,它们具有相同的效果。

library(dplyr)

x <- rlang::quo(cyl)
y <- rlang::sym("cyl")
identical(group_by(mtcars, !!x), group_by(mtcars, !!y))  # TRUE
于 2018-02-14T04:46:38.020 回答