Search code examples
rggplot2pipemagrittr

ggplot2 secondary axis tidyeval


I was wondering if it is possible to specify a secondary axis transformation in ggplot2 with variable references.
In particular I have the following pseudo-code:

df %>%
  group_by(var0) %>%
  summarise(var1 = ...,
            var2 = ...) %>%
  ggplot() +
  geom_bar(aes(x = var0, y = var1), stat = "identity") +
  geom_line(aes(x = var0, y = var2, group = 1))

In this code we have everything plotted on the first axis so we can do:

df %>%
  group_by(var0) %>%
  summarise(var1 = ...,
            var2 = ...) %>%
  ggplot() +
  geom_bar(aes(x = var0, y = var1), stat = "identity") +
  geom_line(aes(x = var0, y = var2 * max(var1) / max(var2), group = 1)) + 
  scale_y_continuous(sec.axis = sec_axis(transform = ~ ./ (max(var1) / max(var2)), name="sec_axis"))

This code does not work because var1 and var2 are not define outside of this piped operations, so I have to do:

df1 <- df %>%
  group_by(var0) %>%
  summarise(var1 = ...,
            var2 = ...)
df1 %>%  
ggplot() +
  geom_bar(aes(x = var0, y = var1), stat = "identity") +
  geom_line(aes(x = var0, y = var2 * max(var1) / max(var2), group = 1)) + 
  scale_y_continuous(sec.axis = sec_axis(transform = ~ ./ (max(df1$var1) / max(df1$var2)), name="sec_axis"))

This works, however I have to create an additional variable, df1 outside of the ggplot chained operations. Is there a way to get the first approach to work?

Thank you


Solution

  • One option would be to wrap the ggplot call in braces which as you are using the magrittr pipe allows to pass the dataset to multiple places.

    Using a minimal reproducible example based on mtcars:

    library(dplyr, warn = FALSE)
    library(ggplot2)
    
    mtcars %>%
      group_by(cyl) %>%
      summarise(
        var2 = mean(mpg)
      ) %>%
      {
        ggplot(., aes(cyl, var2)) +
          geom_col() +
          scale_y_continuous(
            "Miles/gallon",
            sec.axis = sec_axis(function(x) x + max(.$var2))
          )
      }
    

    enter image description here