rfunctionggpubrtidyevalnse

Passing variables to ggpubr from function call


I am looking to wrap the following formula into a function for easier end use:

df %>% 
  group_by(a, b) %>%
  summarize(avg=mean(c)) %>%
  ggline(x="a", y="avg", color='b')

however the following returns the error "Error in is.factor(x) : object 'b' not found" even though is.factor(df$b) == TRUE

graph_var <- function(data_source, var) {
  var2 <- enquo(var)
  
  data_source %>% 
    group_by(a, !!var2 )%>% 
    summarize(avg=mean(c)) %>% 
    ggline(x="a", y="avg", color=shQuote(var) )+ grids(linetype = 'dashed')
}

graph_var(df, b)

I'm sure the issue lies somewhere around ggpubr using quotes in its arguments, but I can't track down exactly what I need to do get this to work.

For reproducibility:

library(tidyverse)
library(ggpubr)

set.seed(13)
df <- data.frame(
  a = rep(1:10),
  b = as.factor(rep(LETTERS[24:26], each = 10)),
  c = rnorm(30)
)

#explicit declatation - this works
df %>% 
  group_by(a, b )%>% 
  summarize(avg=mean(c)) %>% 
  ggline(x="a", y="avg", color="b" )+ grids(linetype = 'dashed') #works

#declaired via variable, this also works
test_var <- "b"

df %>% 
  group_by(a, b )%>% 
  summarize(avg=mean(c)) %>% 
  ggline(x="a", y="avg", color=test_var )+ grids(linetype = 'dashed') #also works

#declaited via f(x) - yeilds error "Error in is.factor(x) : object 'b' not found"
graph_var_ex <- function(data_source, var) {
  var2 <- enquo(var)
  
  data_source %>% 
    group_by(a, !!var2 )%>% 
    summarize(avg=mean(c)) %>% 
    ggline(x="a", y="avg", color=shQuote(var) )+ grids(linetype = 'dashed')
}

graph_var_ex(df, b)

Solution

  • Try as.character(ensym(var)).

    Other notes:

    1. Your function included y="c" in the ggline() call, but this should be y="avg" since "c" no longer exists after your summarize().
    2. You can use the {{ embracing operator as a shortcut for !!enquo() when passing var to group_by().
    library(dplyr)
    library(ggpubr)
    
    # example data
    set.seed(13)
    df <- data.frame(
      a = rep(1:10),
      b = rep(LETTERS[24:26], each = 10),
      c = rnorm(30)
    )
    
    graph_var <- function(data_source, var) {
      var2 <- as.character(ensym(var))
      
      data_source %>% 
        group_by(a, {{var}})%>% 
        summarize(avg = mean(c)) %>% 
        ggline(x = "a", y = "avg", color = var2) + 
        grids(linetype = "dashed")
    }
    
    graph_var(df, b)