我试图了解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
以及如何以新风格进行创作。
答案 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)