Home > Mobile >  How to use tidy evaluation with a non-tidyverse package
How to use tidy evaluation with a non-tidyverse package

Time:10-31

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

  • Related