Функции программирования: NSE в DPLYR и PURRR - PullRequest
1 голос
/ 03 апреля 2019

В настоящее время у меня возникают проблемы с нестандартной оценкой при попытке обернуть функцию вокруг некоторых вычислений, выполненных с помощью dplyr und purrr, которые я использую несколько раз.

Я читал о NSE и думаю, что знаю, где моя функция не работает должным образом, однако я не мог понять, почему это так.

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

 Data <- Data %>%
  group_by(WeekBeforeRelease) %>%
  mutate(visitors_genreother_instr = map_dbl(Genre_Category, ~ mean(Visitors[Genre_Category != .x]))) %>%
  ungroup() %>%
  as.data.frame()

Что превращает эту функцию в следующую, используя NSE, как описано здесь :

Function_Other <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){

  ENDOGVAR <- enquo(ENDOGVAR)
  VARNAME <- quo_name(enquo(VARNAME))
  GROUP_MOVIE <- enquo(GROUP_MOVIE)
  GROUP_TIME <- enquo(GROUP_TIME)

  Data <<- Data %>%
    group_by(!!GROUP_TIME) %>%
    mutate(!!VARNAME := map_dbl(!!GROUP_MOVIE, ~mean(!!ENDOGVAR[!!GROUP_MOVIE != .x]))) %>%
    ungroup() %>%
    as.data.frame()
}

Однако, похоже, это не обрабатывает подмножество в квадратных скобках в расчете на среднее значение. Если я заменил !! ENDOGVAR с посетителями, все работает нормально и как задумано. Однако, как есть, он выдает следующую ошибку:

Error in NextMethod("[") : object '.x' not found 

Я рад любой помощи, которая указывает мне на понимание этой проблемы.

Заранее большое спасибо!

Рондо

1 Ответ

0 голосов
/ 03 апреля 2019

Мы можем заключить !! в фигурные скобки, чтобы избежать какого-либо приоритета операций, и теперь должны нормально работать

library(tidyverse)
Function_Other <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){

  ENDOGVAR <- enquo(ENDOGVAR)
  VARNAME <- quo_name(enquo(VARNAME))
  GROUP_MOVIE <- enquo(GROUP_MOVIE)
  GROUP_TIME <- enquo(GROUP_TIME)

  Data %>%
    group_by(!!GROUP_TIME) %>%
    mutate(!!VARNAME := map_dbl(!!GROUP_MOVIE, ~
           mean((!!ENDOGVAR)[(!!GROUP_MOVIE) != .x]))) %>%
    ungroup() %>%
    as.data.frame()

}


Data <- mtcars
out <- Function_Other(mpg, newcol, am, gear)
head(out, 3)
#   mpg cyl disp  hp drat    wt  qsec vs am gear carb newcol
#1 21.0   6  160 110 3.90 2.620 16.46  0  1    4    4  21.05
#2 21.0   6  160 110 3.90 2.875 17.02  0  1    4    4  21.05
#3 22.8   4  108  93 3.85 2.320 18.61  1  1    4    1  21.05

Обновление

С rlang 0.4.0 (протестировано с dplyr 0.8.2) мы также можем использовать {{...}} для замены, кавычки и кавычки. Предыдущая функция может быть записана как

Function_OtherN <- function(ENDOGVAR, VARNAME, GROUP_MOVIE, GROUP_TIME){  


  Data %>%
    group_by({{GROUP_TIME}}) %>%
    mutate({{VARNAME}} := map_dbl({{GROUP_MOVIE}}, ~
           mean({{ENDOGVAR}}[{{GROUP_MOVIE}} != .x]))) %>%
    ungroup() %>%
    as.data.frame()

}


out1 <- Function_OtherN(mpg, newcol, am, gear)

- проверка с предыдущим выводом

identical(out1, out)
[1] TRUE
...