Search code examples
rdplyrsurvey

lapply to run to run two anonymous functions simultaneously


I have data such as this. I am using the survey package to produce the MEAN, SE and FREQ of each variables in the vector named vars.

library(survey)

df <- data.frame(sex = c('F', 'M', NA, 'M', 'M', 'M', 'F', 'F'),
                 married = c(1,1,1,1,0,0,1,1),
                 pens = c(0, 1, 1, NA, 1, 1, 0, 0),
                 weight = c(1.12, 0.55, 1.1, 0.6, 0.23, 0.23, 0.66, 0.67))


vars <- c("sex","married","pens")

This is my survey design:

design <- svydesign(ids=~1, data=df, weights=~weight)

I am using lapply to find the means:

lapply(vars, function(x) 
    svymean(as.formula(paste0('~interaction(', x, ')')), design, na.rm = T))

I am using lapply to find the freqs:

lapply(vars, function(x) 
    svytable(as.formula(paste0('~interaction(', x, ')')), design))

Is there a way to run lapply over these two functions as the same tine? I would like my output to look like this:

                   mean     SE     freq
interaction(sex)F 0.60345 0.2067    2.45
interaction(sex)M 0.39655 0.2067    1.61

I tried:

lapply(vars, function(x) 
  svymean(as.formula(paste0('~interaction(', x, ')')),
  svytable(as.formula(paste0('~interaction(', x, ')')), design)))

Solution

  • The best way would just be to have the function return both results in a list. But also honestly I find it better if things are getting complicated to create the function outside of the lapply. So this is what I would probably do:

    myfun <- function(x){
      means <- svymean(as.formula(paste0('~interaction(', x, ')')), design, na.rm = T)
      table <- svytable(as.formula(paste0('~interaction(', x, ')')), design)
      results <- list(svymean = means, svytable = table)
      return(results)
    }
    
    lapply(vars, myfun)
    

    You obviously could just do this as an anonymous function like...

    lapply(vars, function(x){
          means <- svymean(as.formula(paste0('~interaction(', x, ')')), design, na.rm = T)
          table <- svytable(as.formula(paste0('~interaction(', x, ')')), design)
          results <- list(svymean = means, svytable = table)
          return(results)
        })
    

    You don't necessarily even need to store the intermediate results

    lapply(vars, function(x){
          list(svymean = svymean(as.formula(paste0('~interaction(', x, ')')), design, na.rm = T), svytable = svytable(as.formula(paste0('~interaction(', x, ')')), design))})
    

    But hopefully you'll agree that isn't pretty.