首页 文章

使用purrr和dplyr:是rlang :: sym最好的方法

提问于
浏览
3

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

为了提供一个具体的例子,假设我想使用 purrr::map_df() 迭代 dplyr::group_by() 中的变量 . programming with dplyr插图通过编写 my_summarise() 函数;方法是在分组变量上使用 rlang::enquo() ,然后用 !! 取消引用 . 这种方法可以创建一个类似于dplyr的新函数,该函数采用不带引号的变量名称(在插图中为 my_summarise(df, g1) ) .

相反,我想purrr提供变量名称作为字符串 . rlang::sym() 是正确的方法吗?它似乎不是,因为在dplyr编程小插图中没有提到 sym() 而在rlang tidy evaluation article中几乎没有提到 . 有没有更好的办法?

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

作为后续行动,为什么简单地取消引用(没有先应用 enquosym )在某些时候工作?在下面的示例中,为什么 select() 按预期工作但 group_by() 不工作?

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

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

其他参考:这是由Edwin Thoen撰写的blog post .

1 回答

  • 1

    简短回答:是的 .

    如果你想 map 在列上, sym 是一个很好的方法 . Lionel Henry在draft vignette中演示 sym .

    如果您想传递列名,但不想尝试迭代,KirillMüllerprefers quo . 在下面的示例中,它们具有相同的效果 .

    library(dplyr)
    
    x <- rlang::quo(cyl)
    y <- rlang::sym("cyl")
    identical(group_by(mtcars, !!x), group_by(mtcars, !!y))  # TRUE
    

相关问题