用dplyr编程时ensym和enquo有什么区别?

Ben*_*n G 6 r dplyr tidyeval rlang

相对较新的 tidy 评估和我正在制作的函数,我想知道为什么使用不同的辅助函数。例如,enquo和之间有什么区别ensym?在我下面制作的用于捕获每日平均值和移动平均值的函数中,它们是可以互换的:

library(dplyr)
library(lubridate)
library(rlang)
library(zoo)

manipulate_for_ma <- function(data, group_var, da_col_name, summary_var, ma_col_name) {
  group_var <- ensym(group_var) 
  summary_var <- enquo(summary_var)
  da_col_name <- ensym(da_col_name) 
  ma_col_name <- enquo(ma_col_name)

  data %>% 
    group_by(!!group_var) %>%
    summarise(!!da_col_name := mean(!!summary_var, na.rm = TRUE)) %>% 
    mutate(!!ma_col_name := rollapply(!!da_col_name,
                                      30,
                                      mean,
                                      na.rm = TRUE,
                                      partial = TRUE,
                                      fill = NA)) %>% 
    rename(date = !!group_var)
}

lakers %>%
 mutate(date = ymd(date)) %>%
 manipulate_for_ma(group_var = date,
                   da_col_name = points_per_play_da,
                   summary_var = points,
                   points_per_play_ma)

# A tibble: 78 x 3
   date       points_per_play_da points_per_play_ma
   <date>                  <dbl>              <dbl>
 1 2008-10-28              0.413              0.458
 2 2008-10-29              0.431              0.459
 3 2008-11-01              0.408              0.456
 4 2008-11-05              0.386              0.457
Run Code Online (Sandbox Code Playgroud)

我读过enquo 这里ensym(这里)[ https://adv-r.hadley.nz/quasiquotation.html]。区别ensym是否更具限制性并且仅采用字符串或类似字符串的对象?

Moo*_*per 5

另一种做法:

library(rlang)
library(dplyr, warn.conflicts = FALSE)

test <- function(x){
  Species <- "bar"
  cat("--- enquo builds a quosure from any expression\n")
  print(enquo(x))
  cat("--- ensym captures a symbol or a literal string as a symbol\n")
  print(ensym(x))
  cat("--- evaltidy will evaluate the quosure in its environment\n")
  print(eval_tidy(enquo(x)))
  cat("--- evaltidy will evaluate a symbol locally\n")
  print(eval_tidy(ensym(x)))
  cat("--- but both work fine where the environment doesn't matter\n")
  identical(select(iris,!!ensym(x)), select(iris,!!enquo(x)))
}

Species = "foo"
test(Species)
#> --- enquo builds a quosure from any expression
#> <quosure>
#> expr: ^Species
#> env:  global
#> --- ensym captures a symbol or a literal string as a symbol
#> Species
#> --- evaltidy will evaluate the quosure in its environment
#> [1] "foo"
#> --- evaltidy will evaluate a symbol locally
#> [1] "bar"
#> --- but both work fine where the environment doesn't matter
#> [1] TRUE

test("Species")
#> --- enquo builds a quosure from any expression
#> <quosure>
#> expr: ^"Species"
#> env:  empty
#> --- ensym captures a symbol or a literal string as a symbol
#> Species
#> --- evaltidy will evaluate the quosure in its environment
#> [1] "Species"
#> --- evaltidy will evaluate a symbol locally
#> [1] "bar"
#> --- but both work fine where the environment doesn't matter
#> [1] TRUE
test(paste0("Spec","ies"))
#> --- enquo builds a quosure from any expression
#> <quosure>
#> expr: ^paste0("Spec", "ies")
#> env:  global
#> --- ensym captures a symbol or a literal string as a symbol
#> Only strings can be converted to symbols
Run Code Online (Sandbox Code Playgroud)

由reprex 包(v0.3.0)于 2019-09-23 创建

  • @BenG:不是为了让事情变得更复杂,但还有`enexpr`,它介于`ensym`和`enquo`之间:1)`enexpr`和`enquo`都允许任意表达式,而`ensym`只允许用于类似“变量名”的表达式;2) `enexpr` 和 `ensym` 都不捕获环境,使得它们的计算依赖于上下文,而 `enquo` 表达式在任何地方总是以相同的方式计算。 (2认同)