在 dplyr v.0.7 中使用 dplyr::arrange 编程

programming with dplyr::arrange in dplyr v.0.7

我正在努力了解 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 显然是 [=18= 的行数],dplyr 的内部函数显然需要这个长度的向量。我的问题是为什么新的编程风格不翻译 arrange 以及如何以新的风格翻译。

你想多了。使用适当的函数来处理...。根本不需要使用 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)
}

在这种情况下您实际上不需要 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)