2

I am somewhat new to writing user defined functions with dplyr and I would like to use dynamically defined variables within my function. I've gotten part of the way there with documentation here and here and here but I am afraid that I might not have the right nomenclature to find what I am trying to do.

I would like to define a function where it creates a variable in a mutate call and then uses that variable in other calls. For example,

library(tidyverse)
library(PropCIs)

for_share_plot <- function(data, dummy, group_var){

    dummy_sum <- paste0(quo_name(enquo(dummy)), "_sum")

    data %>% 
       mutate("{{dummy}}_sum" := sum({{dummy}})) %>% 
       mutate("{{dummy}}_prop" := (!!dummy_sum)/{{group_var}},
              "{{dummy}}_lowerci" := scoreci(!!dummy_sum, {{group_var}}, conf.level = 0.95)$conf.int[1],
              "{{dummy}}_upperci" := scoreci(!!dummy_sum, {{group_var}}, conf.level = 0.95)$conf.int[2])
}

df <- mtcars %>%
    add_count(cyl, name = 'group_n') %>%
    group_by(cyl) %>%
    for_share_plot(data = ., dummy = am, group_var = group_n)

returns the following error message

#Error: Problem with `mutate()` input `am_prop`.
#x non-numeric argument to binary operator
#ℹ Input `am_prop` is `"am_sum"/group_n`.
#ℹ The error occured in group 1: cyl = 4.

I understand that it is interpreting the first input to {{dummy}}_prop as a string but I don't know how else to reference the previously defined column from just above. Any guidance would be much appreciated.

JRR
  • 578
  • 5
  • 21

2 Answers2

2

You correctly identified that dummy_sum is a string, so you can convert it to a symbol that !! can evaluate by using the sym() command.

Try the following modification to your code:

for_share_plot <- function(data, dummy, group_var){

    dummy_sum <- sym(paste0(quo_name(enquo(dummy)), "_sum"))

    data %>% 
       mutate("{{dummy}}_sum" := sum({{dummy}})) %>% 
       mutate("{{dummy}}_prop" := (!!dummy_sum)/{{group_var}},
              "{{dummy}}_lowerci" := scoreci(!!dummy_sum, {{group_var}}, conf.level = 0.95)$conf.int[1],
              "{{dummy}}_upperci" := scoreci(!!dummy_sum, {{group_var}}, conf.level = 0.95)$conf.int[2])
}
latlio
  • 1,567
  • 7
  • 15
1

You can use .data pronoun to refer to column names.

library(dplyr)
library(PropCIs)

for_share_plot <- function(data, dummy, group_var){
  
  dummy_sum <- paste0(quo_name(enquo(dummy)), "_sum")
  
  data %>% 
    mutate("{{dummy}}_sum" := sum({{dummy}}),
           "{{dummy}}_prop" := .data[[dummy_sum]]/{{group_var}},
           "{{dummy}}_lowerci" := scoreci(.data[[dummy_sum]], {{group_var}}, conf.level = 0.95)$conf.int[1],
           "{{dummy}}_upperci" := scoreci(.data[[dummy_sum]], {{group_var}}, conf.level = 0.95)$conf.int[2])
}

mtcars %>%
  add_count(cyl, name = 'group_n') %>%
  group_by(cyl) %>%
  for_share_plot(dummy = am, group_var = group_n)
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213