用dplyr编译::在dplyr v.0.7中安排

时间:2017-07-19 08:55:52

标签: r dplyr nse non-standard-evaluation

我试图了解dplyr中关于编程和非标准评估的新实现。因此,verb_函数被参数的enquo替换,然后在常规动词函数中应用!!。将select从旧版翻译为新版可以正常工作,以下函数会给出类似的结果:

select_old <- function(x, ...) {
  vars <- as.character(match.call())[-(1:2)]
  x %>% select(vars)
}

select_new <- function(x, ...) {
  vars <- as.character(match.call())[-(1:2)]
  vars_enq <- enquo(vars)
  x %>% select(!!vars_enq)
}

但是,当我尝试在新的编程风格中使用arrange时,我会收到错误:

arrange_old <- function(x, ...) {
  vars <- as.character(match.call())[-(1:2)]
  x %>% arrange_(vars)
}

arrange_new <- function(x, ...){
  vars <- as.character(match.call())[-(1:2)]
  vars_enq <- enquo(vars)
  x %>% arrange(!!vars_enq)
}

mtcars %>% arrange_new(cyl)     
# Error in arrange_impl(.data, dots) : 
#  incorrect size (1) at position 1, expecting : 32

32显然是mtcars的行数,dplyr的内部函数显然需要这个长度的向量。我的问题是为什么新的编程风格不适用于arrange以及如何以新风格进行创作。

2 个答案:

答案 0 :(得分:2)

你正在思考它。使用适当的函数来处理...。根本不需要使用match.call(实际上也不是旧版本)。

arrange_new <- function(x, ...){
  dots <- quos(...)
  x %>% arrange(!!!dots)
}

当然这个函数与普通arrange完全相同,但我想你只是以此为例。

您可以用同样的方式编写select函数。

arrange_old应该看起来像:

arrange_old <- function(x, ...){
  dots <- lazyeval::lazy_dots(...)
  x %>% arrange_(.dots = dots)
}

答案 1 :(得分:1)

在这种情况下,你实际上并不需要rlang。这将有效:

my_arrange <- function(x, ...) arrange(x, ...)

# test
DF <- data.frame(a = c(2, 2, 1, 1), b = 4:1)
DF %>% my_arrange(a, b)