Доступ к новым переменным в функции dplyr

Я пишу функцию для расчета коэффициентов шансов для таблицы отсчетов, которая требует оценки NSE с помощью dplyr и tidyr. Как может быть очевидно, это мое первое предприятие в мире NSE.

Например, с фреймом данных 'foo':

# A tibble: 4 x 3
   strata   group     select
    <chr>   <chr>      <chr>
1 Manager A_Group     Chosen
2  Worker A_Group     Chosen
3 Manager B_Group Not_Chosen
4  Worker B_Group     Chosen
5 ...

Я сначала делаю счет: foo2 <- foo %>% count(strata, group, select)

# A tibble: 8 x 4
   strata   group     select     n
    <chr>   <chr>      <chr> <int>
1 Manager A_Group     Chosen     1
2 Manager A_Group Not_Chosen     9
3 Manager B_Group     Chosen     1
4 Manager B_Group Not_Chosen     3
5 ...

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

foo2 %>% unite(cat, c(group, select)) %>% 
    spread(cat, n, fill = 0)

# A tibble: 2 x 5
strata A_Group_Chosen A_Group_Not_Chosen B_Group_Chosen B_Group_Not_Chosen
*   <chr>          <dbl>              <dbl>          <dbl>              <dbl>
1 Manager              1                  9              1                  3
2  Worker              1                 11              1                  3

И наконец, я рассчитываю новый столбец, ИЛИ как

 ... %>% mutate(OR = (A_Group_Chosen * B_Group_Not_Chosen) /
  (A_Group_Not_Chosen * B_Group_Chosen))

Чтобы поместить этот код в функцию, я обрабатываю исходные столбцы с помощью enquo и!!, но для вычисления нового столбца, ИЛИ, мне нужны вновь созданные столбцы (именуемые путем объединения значений группы и столбцов выбора). Вопрос заключается в том, как "заключить в кавычки" имена для расчета ИЛИ?

Мой текущий черновик сохраняет промежуточный результат после объединения / распространения, помещает имена в вектор и использует оператор $`!!'(). Это чувствует себя довольно грязно. Лучше?

Моя функция:

OR_tab <- function(dat, strat, grp, decision ){
  strat <- enquo(strat)
  grp <- enquo(grp)
  decision <- enquo(decision)



  tab <- dat %>% count(!!strat, !!grp, !!decision) %>% unite(cat, c(!!grp, !!decision)) %>% 
    spread(cat, n, fill = 0)
  nm <- names(tab)[2:5]
  tab %>% mutate(OR = (tab$`!!`(nm[1]) * tab$`!!`(nm[4])) / (tab$`!!`(nm[2]) * (tab$`!!`(nm[3])))) %>% 
    print(n = Inf)
}

OR_tab(foo, strata, group, select)

Мой оригинальный фрейм данных 'foo':

> dput(foo2)
structure(list(strata = c("Manager", "Worker", "Manager", "Manager", 
"Worker", "Manager", "Manager", "Manager", "Worker", "Worker", 
"Worker", "Worker", "Worker", "Worker", "Manager", "Worker", 
"Worker", "Manager", "Manager", "Manager", "Worker", "Worker", 
"Manager", "Manager", "Manager", "Manager", "Worker", "Worker", 
"Worker", "Worker"), group = c("A_Group", "A_Group", "A_Group", 
"A_Group", "B_Group", "A_Group", "B_Group", "A_Group", "A_Group", 
"A_Group", "A_Group", "A_Group", "B_Group", "B_Group", "A_Group", 
"A_Group", "A_Group", "A_Group", "A_Group", "B_Group", "A_Group", 
"A_Group", "B_Group", "B_Group", "A_Group", "A_Group", "B_Group", 
"A_Group", "A_Group", "A_Group"), select = c("Chosen", "Chosen", 
"Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", 
"Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", 
"Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", 
"Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", "Not_Chosen", 
"Not_Chosen", "Chosen", "Not_Chosen", "Not_Chosen", "Chosen", 
"Not_Chosen", "Not_Chosen", "Not_Chosen")), .Names = c("strata", 
"group", "select"), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-30L))

1 ответ

Вы можете избежать необходимости отмены цитирования после spread выполнив расчет отношения шансов для длинных данных (как предложено @MrFlick):

library(tidyverse)

OR_tab2 <- function(dat, strat, grp, decision ){

  strat <- enquo(strat)
  grp <- enquo(grp)
  decision <- enquo(decision)

  dat %>% 
    count(!!strat, !!grp, !!decision) %>% 
    group_by(!!strat) %>% 
    mutate(OR = (n[1]*n[4])/(n[2]*n[3])) %>% 
    unite(cat, c(!!grp, !!decision)) %>% 
    spread(cat, n)

}

OR_tab2(foo2, strata, group, select)
  strata     OR A_Group_Chosen A_Group_Not_Chosen B_Group_Chosen B_Group_Not_Chosen
  <chr>   <dbl>          <int>              <int>          <int>              <int>
1 Manager 0.333              1                  9              1                  3
2 Worker  0.273              1                 11              1                  3

Как и с вашим исходным кодом, это будет работать для любого фрейма данных, где group а также select Каждый аргумент имеет только два уровня, но какие пары уровней находятся в числителе или знаменателе, будет зависеть от порядка уровней в каждом столбце. Например, обратите внимание, что для перекодированного фрейма данных df2 ниже отношения шансов инвертированы относительно коэффициентов исходного кадра данных df,

df2 = foo2 %>% 
  mutate(experimental_groups = recode(group, 
                        "A_Group"="Control",
                        "B_Group"="Treatment"),
         flavor = recode(select, 
                         "Chosen"="Vanilla",
                         "Not_Chosen"="Chocolate"))

OR_tab2(df2, strata, experimental_groups, flavor)
  strata     OR Control_Chocolate Control_Vanilla Treatment_Chocolate Treatment_Vanilla
  <chr>   <dbl>             <int>           <int>               <int>             <int>
1 Manager  3.00                 9               1                   3                 1
2 Worker   3.67                11               1                   3                 1
OR_tab(df2, strata, experimental_groups, flavor)
  strata  Control_Chocolate Control_Vanilla Treatment_Chocolate Treatment_Vanilla    OR
  <chr>               <dbl>           <dbl>               <dbl>             <dbl> <dbl>
1 Manager                9.              1.                  3.                1.  3.00
2 Worker                11.              1.                  3.                1.  3.67
Другие вопросы по тегам