Я пытаюсь разработать функцию, которая будет вычислять средние значения, стандартную ошибку и доверительные интервалы некоторых данных опроса. Мне нужно сделать это несколько раз для нескольких разных переменных с кучей разных операторов фильтра.
ДАННЫЕ
df <- data.frame(address_id = rep(c(1,1,1,2,2,2,3,3,3,4,4,4),5),
person_id = rep(c(1,2,3),20),
sex = as.factor(rep(c("male","female"),30)),
response_var = as.factor(rep(seq(1,6,1))),
weight = runif (60, 50, 200))
Пример, который работает без функции
# create survey design
design <- survey::svydesign(data = df,
strata = ~ address_id,
id = ~ person_id,
nest = TRUE,
weights = ~ weight)
# calcualte weighted mean
mean_se <- survey::svymean(~sex, design)
# calculate confidence intervals
ci <- survey::confint(df_mean)
Моя функция
create_mean_and_cis <- function(data, var){
design <- survey::svydesign(data = data,
strata = ~ address_id,
id = ~ person_id,
nest = TRUE,
weights = ~ weight)
mean_se <- survey::svymean(~{{var}}, design)
ci <- confint(mean_se)%>%
tibble::as_tibble()%>%
tibble::rownames_to_column("variable")
output <- mean_se%>%
tibble::as_tibble()%>%
tibble::rownames_to_column("variable")%>%
dplyr::left_join(ci)
return(output)
}
# function call
create_mean_and_cis(sex)
Когда я запускаю, я получаю сообщение об ошибке:
Error in survey::svydesign(data = data, strata = ~address_id, id = ~person_id, :
object 'sex' not found
Я не могу понять, что происходит. Аккуратная оценка отлично работает, когда я использую фигурные "{{var}}" в других функциях. Почему здесь не работает? Кто-нибудь может помочь?
Я пробовал несколько вариантов квазицитирования, в том числе: !!enquo(sex), sym(sex), !!sym(sex), {{sex}}, eval(parse(sex)). Ни один из них не дал рабочих результатов.
Фактическая ошибка, которую вы получаете, заключается в том, что вы не передаете аргумент data
в create_mean_and_cis
(вы делаете create_mean_and_cis(sex)
, тогда как это должно быть create_mean_and_cis(df, sex)
).
Однако само по себе это не решит проблему, так как оператор фигурный-кудрявый не будет работать внутри формулы. Вместо этого вам нужно сделать что-то вроде:
create_mean_and_cis <- function(data, var){
var <- deparse(substitute(var))
design <- survey::svydesign(data = data,
strata = ~ address_id,
id = ~ person_id,
nest = TRUE,
weights = ~ weight)
mean_se <- survey::svymean(as.formula(paste('~', var)), design)
ci <- confint(mean_se)%>%
tibble::as_tibble()%>%
tibble::rownames_to_column("variable")
output <- mean_se%>%
tibble::as_tibble()%>%
tibble::rownames_to_column("variable")%>%
dplyr::left_join(ci)
return(output)
}
Который позволяет
create_mean_and_cis(df, sex)
#Joining, by = "variable"
## A tibble: 2 x 5
# variable mean SE `2.5 %` `97.5 %`
# <chr> <dbl> <dbl> <dbl> <dbl>
# 1 1 0.481 0.163 0.161 0.802
# 2 2 0.519 0.163 0.198 0.839
Вместо paste("~", var)
можно было бы попробовать reformulate(var)
,
Если вы хотите использовать более продвинутые функции аккуратной оценки, вы можете использовать rlang::eval_tidy
mean_se <- rlang::eval_tidy(rlang::quo(survey::svymean(~{{var}}, design)))
Вы заключаете свое выражение в квазуру, где вы можете использовать синтаксис стилей {{ }}
и !!
. И quo
, и eval_tidy
распознают этот синтаксис. Эти функции уникальны для функций, использующих пакет rlang
; вы не можете использовать их напрямую в любой произвольной функции R без какой-либо оболочки rlang
.
Или, по предложению @Lionel, вы можете использовать rlang::inject
, чтобы построить формулу и передать ее svymean
formula <- rlang::inject(~!!substitute(var))
mean_se <- survey::svymean(formula, design)
Вы также можете вводить в формулу с помощью inject()
, но никогда не вводите quosure, а только голые выражения. Затем формулу можно использовать в базовых функциях.
@LionelHenry Я обновил пост тем, что, как я думаю, вы предлагали. Если это не так, дайте мне знать.
о, я имел в виду inject(~ !!substitute(var))
. Синтаксис {{
создает quosure, который совместим только с функциями tidyverse NSE.
Другой подход заключается в использовании пакета tidyversatile
srvyr
, который обертываетsurvey