使用tidyr :: expand的非标准评估

时间:2019-09-23 20:00:12

标签: r tidyr nse

我在使用tidyr包运行非标准评估(nse)表达式时遇到麻烦。

基本上,我想做的是扩展两列,这些列可能相同或不同,以使用所有可能的组合获得一个数据框。问题在于这将是一个函数,因此我不会提前知道列名。

这是一个最小的示例:

library(tidyr)

dummy <- data.frame(x = c("ex1", "ex2"), y = c('cat1', 'cat2')) # dataset

tidyr::expand(dummy, x, y) # using standard evaluation works
tidyr::expand_(dummy, c("x", "y"))  # using the deprecated syntax works

# The following did not work:

  tidyr::expand(dummy, one_of('x'), y) # using select syntax
  tidyr::expand(dummy, vars('x', 'y')) # mutate_at style
  tidyr::expand(dummy, .data[[cnae_agg]], .data[[cnae_agg]])  # mutate current style  
  tidyr::expand(dummy, sym('x'), sym('y')) # trying to convert to symbols
  tidyr::expand(dummy, !!!enquos('x', 'y')) 
  tidyr::expand(dummy, !!('x'), y) # unquosure just one element
  tidyr::expand(dummy, !!!c("x", "y")) # unquosure vector of strings
  tidyr::expand(dummy, !!!c(quo("x"), quo("y"))) # unquosure vector that is being quosured before

所以,我有两个问题:

1)tidyr扩展功能将使用什么正确的语法?

2)我可能已经读过几次Advanced R的准引用,但是我仍然不清楚为什么在nse的tidyverse中使用几种不同的'样式',以及在哪里确切地使用每个。

我基本上可以扔出几乎所有东西来选择/总结它会起作用,但是当使用mutate时,事情的反应会有所不同。

例如:

  # mutate
  mutate(dummy, new_var = .data[['x']]) # mutate basic style
  mutate(dummy, new_var = !!'x') # this just attributes 'x' to all rows


  # mutate at
  mutate_at(dummy, .vars=vars('y'), list(~'a')) # this works
  mutate_at(dummy, .vars=vars(!!'y'), list(~'a')) # this also works
  mutate_at(dummy, .vars=vars('y'), list(~`<-`(.,!!'x'))) # if we try to use unquote to create an attribution it does not work
  mutate_at(dummy, .vars=vars('y'), list(~`<-`(.,vars(!!'x')))) # even using vars, which works for variable selection, doesnt suffice

  # select 
  select(dummy, x) # this works
  select(dummy, 'x') # this works
  select_at(dummy, vars(!!'x')) # this works
  select_at(dummy, 'x') # this works
  select_at(dummy, !!'x') # this doesnt work

将我带到我的2)问题。

是否有更新的指南,用于tidyverse样式的所有当前语法,重点关注每个“动词”用法的差异,例如“ mutate”与“ select”(即,当一个起作用而另一个起作用时)不)?

又如何知道我是否必须在其他tidyverse程序包(例如tidyr)中使用nse的突变或选择样式?

2 个答案:

答案 0 :(得分:2)

nse上的最新指南是tidy evaluation guide。特别是,第8章介绍了它与dplyr的关系以及一般模式。在您的情况下,有几种可能的模式,具体取决于您要向用户公开的内容。

模式1:只需pass the dots to expand,即可让用户完全控制基础expand()

f <- function(...) {tidyr::expand(dummy, ...)}
f( x, y )    # End users specifies the columns via NSE

模式2::按变量捕获用户输入,并使用new "curly curly" operator将其传递给expand()

g <- function( var1, var2 ) {tidyr::expand(dummy, {{var1}}, {{var2}})}
g( x, y )    # Once again, NSE, but the number of arguments is controlled

模式3::允许用户提供参数作为变量名或字符串。使用rlang::ensyms将字符串转换为变量名:

h <- function(...) {tidyr::expand(dummy, !!!rlang::ensyms(...))}

# The interface now works with strings or NSE
h( "x", "y" )
h( x, y )

模式3b::如果要禁用NSE支持,并强制用户仅以字符串形式提供参数,则对上述模式的较小修改将仅接受字符串:

h2 <- function(...) {tidyr::expand(dummy, !!!rlang::syms(list(...)))}
h2( "x", "y" )    # Strings OK
h2( x, y )        # Error: object 'x' not found

请注意,NSE函数需要quasiquotation来处理存储在外部变量中的符号:

# Handling strings in external variables
str_name <- "x"
h( !!str_name, "y" )
h2( str_name, "y" )    # h2 doesn't support NSE; no !! needed

# Handling variable names as unevaluated expressions (NOT strings)
var_name <- quote(y)
f( x, !!var_name )
g( x, !!var_name )
h( x, !!var_name )

# Handling lists of variable names using !!! unquote-splice
# Works with functions that accept dots
arg_names <- rlang::exprs( x, y )
f( !!!arg_names )
h( !!!arg_names )

答案 1 :(得分:1)

我们需要评估(!!个bols {p}

sym

当列名存储在tidyr::expand(dummy, !!! syms(c('x', 'y'))) # A tibble: 4 x 2 # x y # <fct> <fct> #1 ex1 cat1 #2 ex1 cat2 #3 ex2 cat1 #4 ex2 cat2 中并且想要执行vector

时,这将特别有用。
expand

在某些其他组合中,nm1 <- c('x', 'y') tidyr::expand(dummy, !!! syms(nm1)) 向量中缺少!!!或向sym bol的转换