Доступ к новым переменным в функции 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