fernando schuh
fernando schuh

Reputation: 81

Reverse secondary y-axis plot with ggplot2

I've tried searching stack overflow for the answer but I couldn't get it.

I'm using a reversed y axis to plot one y variable over time and I wanted to get my secondary y axis in normal order (not reversed).

library(tidyverse)
library(scales)
library(lemon)

    base_nivelprecip %>%
      mutate(nivel = as.double(nivel),
             precip = as.double(precip)) %>% 
      mutate(precip_rescaled = precip/200) %>% 
      ggplot(aes(x = data, y = nivel,
                 xmin = as.POSIXct("2012-05-01", "%Y-%m-%d"), 
                 xmax = as.POSIXct("2020-04-30",  "%Y-%m-%d"))) + 
    
      geom_col(aes(x = data, y = precip_rescaled), fill = '#8D8DAA', size = 3) +
      geom_line(group = 1, color = '#041562', size = 0.3) +
      labs(x = "", y = "Groundwater level (m)") +
      scale_y_reverse(limits = c(5,-0.5) ,  sec.axis = sec_axis(~rev(.)*200, name = "Precipitation (mm)")) +
      lemon::facet_rep_wrap(~poco, nrow = 3, repeat.tick.labels = TRUE) +
      theme_bw() +
      theme(text=element_text(size=12),
            axis.text.x = element_text(size = 8)

Although I've tried some transformations, the best I could get was this: enter image description here

But I wanted the geom_col (in secondary axis) to start at the secondary axis 0, not at the primary axis. Can somebody help me? Thanks. A sample of my data is here: https://docs.google.com/spreadsheets/d/1xgj3Gan1Lj9qO2aEGdLpiUOBk9g8USMS/edit?usp=sharing&ouid=111814647952336460862&rtpof=true&sd=true

Upvotes: 2

Views: 1098

Answers (2)

Allan Cameron
Allan Cameron

Reputation: 173803

Perhaps the easiest way to achieve this is to "fake" the primary axis in the same way that you fake the secondary axis. That way, you don't need the added complication of scale_y_reverse:

library(tidyverse)
library(scales)
library(lemon)

base_nivelprecip %>%
  mutate(nivel = as.double(nivel),
         precip = as.double(precip),
         data = as.POSIXct(data, format = "%m/%d/%Y")) %>% 
  mutate(precip_rescaled = precip/200 ,
         nivel_rescaled = -nivel + 2.5) %>% 
  ggplot(aes(x = data, y = nivel_rescaled,
             xmin = as.POSIXct("2012-05-01", "%Y-%m-%d"), 
             xmax = as.POSIXct("2020-04-30",  "%Y-%m-%d"))) +

  geom_col(aes(x = data, y = precip_rescaled), 
           colour = '#8D8DAA', size = 1) +
  geom_line(color = '#041562', size = 0.3) +
  labs(x = "", y = "Groundwater level (m)") +
  scale_y_continuous(labels = function(x) -(x - 2.5), limits = c(0, 2.5),
                  sec.axis = sec_axis(~.*200, 
                                      name = "Precipitation (mm)")) +
  lemon::facet_rep_wrap(~poco, nrow = 3, repeat.tick.labels = TRUE) +
  theme_bw() +
  theme(text=element_text(size=12),
        axis.text.x = element_text(size = 8))

enter image description here

Upvotes: 1

Jon Spring
Jon Spring

Reputation: 66435

Keep in mind that in ggplot2, secondary axes are a decoration that does not change the mapping of your data. So if you want your data to be mapped to a secondary axis, you need to transform it to appear where you want in terms of the primary axis (it's not like Excel where that happens automatically). Then you also need to define the transformation of the secondary axis.

In the case below, I have a reversed primary axis which determines the placement of the points. I also have a secondary axis that transforms the primary axis into the opposite slope. Here, ~35-. means "transform so that the value for input 0 turns into 35, and the slope is reversed."

ggplot(mtcars, aes(wt, mpg)) +
  geom_point() +
  scale_y_continuous(trans = "reverse",
    sec.axis = sec_axis(~35-., name = "how far below 35 mpg"))

enter image description here

Upvotes: 1

Related Questions