Search code examples
rggplot2dplyrrlangtidyeval

Using a linear operation of two programatically defined variables as an aesthetic in ggplot


I'm struggling to write a very simple wrapper to produce plots for different variables. Say my data is:

data <- tibble(year = seq(2001,2015),var1 = rnorm(15, mean=2), var1_sd = rnorm(15, mean=1, sd=0.8), var2 = rnorm(15, mean=7), var2_sd = rnorm(15, mean=1, sd=0.15))

and the plot I want to make is

ggplot(data,aes(x=year, y=var1)) + 
    geom_pointrange(aes(ymin=var1-var1_sd, ymax=var1+var1_sd))

I want to make the exact same plot for a number of variable combinations, so I wrote a wrapper:

myplot <- function(data, var) {
  var <- enquo(var)
  sdvar <- paste0(quo_name(var), "_sd")
  ggplot(data,aes(x=year, y=!!var)) +
    geom_pointrange(aes(ymin=!!var-!!sdvar, ymax=!!var+!!sdvar))
}

When I call myplot(data, var1), I get the error "Error in (~var1) - "var1_sd" : non-numeric argument to binary operator"

I think the problem is in the linear operation between the unquoted variables? Does anyone know how to get around this?

Thanks!!!


Solution

  • At the moment, sdvar is just a string. You can turn it into a symbol with sym(), and then the unquoting works:

    myplot <- function(data, var) {
        var <- enquo(var)
        sdvar <- sym(paste0(quo_name(var), "_sd"))
        ggplot(data,aes(x=year, y=!!var)) +
            geom_pointrange(aes(ymin=!!var-!!sdvar, ymax=!!var+!!sdvar))
    }