программирование с помощью dplyr::arrange в dplyr v.0.7

Я пытаюсь разобраться с новыми реализациями в dplyr в отношении программирования и нестандартной оценки. Таким образом, функции глагола_ заменяются на 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 и как это сделать тогда в новом стиле.


person Edwin    schedule 19.07.2017    source источник


Ответы (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)
}
person Axeman    schedule 19.07.2017
comment
Спасибо, боюсь, пропустил эту часть виньетки. - person Edwin; 19.07.2017
comment
На самом деле не все так однозначно. Но, глядя на источник, например. dplyr:::select.data.frame помогает. - person Axeman; 19.07.2017

На самом деле вам не нужен 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)
person G. Grothendieck    schedule 19.07.2017
comment
Вау вау. Это работает, потому что arrange применяет rlang внутри? - person Edwin; 19.07.2017
comment
Это использует только базу R и работает с любой функцией R. rlang не участвует. Это не относится к dplyr. - person G. Grothendieck; 19.07.2017