I am trying to develop a function which will calculate the means, standard error, and confidence intervals of some survey data. I need to do this repeatedly over a number of different variables with a bunch of different filter statements.
DATA
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))
Example that works without function
# 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)
My function
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)
When I run, I get an error message saying:
Error in survey::svydesign(data = data, strata = ~address_id, id = ~person_id, :
object 'sex' not found
I can't understand what is going wrong. The tidy evaluation works perfectly when I use the curly-curly "{{var}}" within other functions. Why doesn't it work here? Can anyone help?
I have tried several variations of quasiquotation including: !!enquo(sex), sym(sex), !!sym(sex), {{sex}}, eval(parse(sex)). None of which have yielded working results.
CodePudding user response:
The actual error you are getting is because you aren't passing the data
argument to create_mean_and_cis
( you are doing create_mean_and_cis(sex)
whereas it should be create_mean_and_cis(df, sex)
).
However, this will not on its own fix the problem, since the curly-curly operator won't work inside a formula. Instead, you need to do something like:
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)
}
Which allows
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
CodePudding user response:
If you wanted to use more advanced tidy evaulation features, you can use rlang::eval_tidy
mean_se <- rlang::eval_tidy(rlang::quo(survey::svymean(~{{var}}, design)))
You wrap your expression in a quosure where you can use the {{ }}
and !!
style syntax. Both quo
and eval_tidy
will recognize this syntax. These features are unique to functions that use the rlang
package; you cannot use them directly any arbitrary R function without some sort of rlang
wrapper