Нестандартная оценка в цикле R for: входная переменная без кавычек в функции, содержащей dplyr summarize, всегда возвращает NA, но функция фильтра работает

КРАТКОЕ СОДЕРЖАНИЕ

dplyr unquoting не работает как аргумент функции summarise, где цитируемый объект является аргументом функции, использующей summarise, и этот аргумент назначается в цикле for.

For Loop

for(j in 1:1){
  sumvar  <- paste0("randnum",j)
  chkfunc(sumvar)
}

Функция (здесь сокращенно, полностью показано ниже)

chkfunc <- function(sumvar) {
sumvar <- enquo(sumvar)
[...]
    summarise(mn = mean(!!sumvar))

введите здесь описание изображения

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ

У меня есть два столбца, которые иногда содержат НП, и я хочу использовать dplyr нестандартное вычисление и его знаменитое исключение кавычек (AKA bang bang !!) для объединения каждого столбца в один цикл for.

library(dplyr)
set.seed(3)
randnum1 <- rnorm(10)
randnum1[randnum1<0] <- NA
randnum2 <- rnorm(10)
randnum2[randnum2<0] <- NA
randfrm <- data.frame(cbind(randnum1, randnum2))
print(randfrm)

введите здесь описание изображения

Ниже мы видим, что функция фильтра прекрасно обрабатывает отмену кавычек (!!), но функция суммирования дает сбой, возвращая ошибку «аргумент не является числовым или логическим». То же самое происходит, когда я использую := в вызове функции суммирования (здесь не показан), который появился в "Программирование с dplyr" виньетка. Наконец, я подтвердил, что класс для !!sumvar является числовым внутри функции chkfunc.

chkfunc <- function(sumvar) {
  sumvar <- enquo(sumvar)

  message("filter function worked with !!sumvar")
  outfrm <- randfrm %>%
    filter(!is.na(!!sumvar))
  print(outfrm)
  message("summarise function failed with !!sumvar")
  outfrm <- randfrm %>%
             filter(!is.na(!!sumvar)) %>%
             summarise(mn = mean(!!sumvar))
}
# Just one iteration to avoid confusion
for(j in 1:1){
  sumvar  <- paste0("randnum",j)
  chkfunc(sumvar)
}

введите здесь описание изображения


person Rick Pack    schedule 22.11.2017    source источник


Ответы (1)


Хотя я хотел бы получить ответ с помощью dplyr, следующее работает с substitute и eval вместо использования функций dplyr (ответ адаптирован из Ответ Akrun на вопрос StackOverflow" Отменить кавычки в команде замены R "):

chkfunc <- function(sumvar) {
  outfrm <- eval(substitute(randfrm %>%
                            filter(!is.na(y)) %>%
                            summarise(mn = mean(y)),
                            list(y=as.name(sumvar))))
  print(outfrm)
} 

for(j in 1:2){
  sumvar  <- paste0("randnum",j)
  chkfunc(sumvar)
}

print(outfrm)

введите здесь описание изображения

Наконец, я отмечу, что, хотя функция pull на !!sumvar показала, что результирующий класс является числовым (т. Е. Тот же класс и значения randfrm$randnum1), я понял, что !!sumvar обрабатывается как строка символов (т.е. "randnum1) в обоих случаях, когда я использую filter и summarise, отсюда и предупреждение argument is not numeric.

person Rick Pack    schedule 22.11.2017