rdplyrstargazertidyeval

Tidy eval failing within a function


I'm trying to automate the production of .tex tables and I want to add in the add.lines section of stargazer a value called mean_outcome but I'm having trouble producing this value, I think I'm dealing wrong with tidy eval. I have tried quo, enquo, !!, `` but nothing is working.

df <- tibble::tribble(~hhid, ~treatment_arm, ~round_pooled, ~tot_lstock_count, ~tot_animal_tlu,
                      "1020201023",1,1,10,1,
                      "1020201023",1,11,6,0.600000023841858,
                      "1020201036",1,1,10,0.100000001490116,
                      "1020201036",1,11,4,0.400000005960464,
                      "1020201039",1,1,9,0.0900000035762787,
                      "1020201057",1,1,12,0.480000019073486,
                      "1020201068",1,1,2,0.200000002980232,
                      "1020201095",1,1,6,0.330000013113022,
                      "1020201095",1,11,7,0.400000005960464,
                      "1020201103",1,1,2,0.200000002980232,
                      "1020201116",1,1,7,0.0599999986588955,
                      "1020201116",1,11,2,0.0199999995529652,
                      "1020201139",1,11,12,0.480000019073486,
                      "1020201144",1,1,5,0.5,
                      "1020201144",1,11,8,0.800000011920929,
                      "1020201146",1,1,6,0.0599999986588955,
                      "1020201146",1,11,6,0.0599999986588955,
                      "1020201159",1,11,15,1.5,
                      "1020201180",1,11,11,0.560000002384186,
                      "1020201205",1,1,2,0.0199999995529652)

reg_coef_tables <- function(df, y) {
  
  outcome = eval(`i`)  
  
  mean_outcome  <- df %>% 
    
    filter(round_pooled == 11 & treatment_arm == 1) %>% 
    
    summarise(mean = mean(!!outcome, na.rm = T)) %>% 
    
    pull(mean)
  
  reg1 <- felm(outcome ~ treatment_arm, data = df)

stargazer(reg1,
          align = TRUE, 
          dep.var.labels = c("(1)"),
          omit.stat = c("f", "adj.rsq", "ser"),
          no.space = TRUE,
          digits = 3, # number of decimals
          add.lines = list(c('Mean outcome', rep(`mean_outcome`, 1)),
                           dep.var.caption = "", # remove dep var header
                           out = paste0(outcome, ".tex"))
}          
          
liv_vars  = c("tot_lstock_count", "tot_animal_tlu")
liv_out_list = vector("list", 2)
for(i in liv_vars) {
            liv_out_list[[i]] <- reg_coef_tables(df, i)
}


Solution

  • Leaving aside stargazer (because, IMHO, it's horrible) and felm (because I don't know which package it's from) and because neither are relevant to your problem with tidyverse, try this

    reg_coef_tables <- function(df, y) {
      outcome = as.name(y) 
      mean_outcome  <- df %>% 
        filter(round_pooled == 11 & treatment_arm == 1) %>% 
        summarise(mean = mean(!!outcome, na.rm = T)) %>% 
        pull(mean)
    }
    liv_vars  = c("tot_lstock_count", "tot_animal_tlu")
    liv_out_list = list()
    for(i in liv_vars) {
      liv_out_list[[i]] <- reg_coef_tables(df, i)
    }  
    liv_out_list
    $tot_lstock_count
    [1] 7.888889
    
    $tot_animal_tlu
    [1] 0.5355556          
    

    Or, perhaps more succinctly:

    mean_outcome <- df %>% 
      filter(round_pooled == 11 & treatment_arm == 1) %>% 
      summarise(
        across(
          c(tot_lstock_count, tot_animal_tlu), 
          \(x) mean(x, na.rm = TRUE)
        )
      )
    mean_outcome
    # A tibble: 1 × 2
      tot_lstock_count tot_animal_tlu
                 <dbl>          <dbl>
    1             7.89          0.536
    

    You can find a useful primer on NSE here.