0
Date Mn Fe
2013-01-13 67.7 1990
2014-01-13 60.8 2082
2015-01-13 57.1 3901
2016-01-13 40.8 7022
2017-01-13 30.8 5063
2018-01-13 50.3 2032
2019-01-13 20.8 6225
2020-01-13 43.1 8853
2021-01-13 53.8 4048
2022-01-13 33.1 6238

When I make the plot (code below), the Mn-line appears as a straight line compared with the Fe-line. It is because of the low Mn values. I was wondering if anyone could help me to create two independent Y axis in a single plot so that both Fe and Mn could represent their pattern independent of each other along the same X-axis.

  t<-  ggplot(data = stack.data, aes(x= Date)) +
  geom_line(aes (y = Mn,color = "Mn"),  size = 1.4) +
  geom_line(aes (y = Fe, color = "Fe"), size = 1.4) +
  scale_y_continuous(name = "Mn",
                 sec.axis = sec_axis(trans = ~.*10, name="Fe"))+
  scale_color_manual("", values = c( "#F8766D", "#00BFC4")) +
  theme_bw()+
  theme(legend.position="top")
  t
Peter
  • 11,500
  • 5
  • 21
  • 31
  • 1
    Hey Sankar - unfortunately two y-axis with different scales are hard to create in ggplot2. The package creator has a vendetta against them. Find some examples for how to do it here: https://stackoverflow.com/questions/3099219/ggplot-with-2-y-axes-on-each-side-and-different-scales – Henry Holm Oct 13 '22 at 17:48
  • 1
    https://stackoverflow.com/a/66055331/9429625 this solution especially I have found useful. – Henry Holm Oct 13 '22 at 17:51

2 Answers2

2

Maybe using a log scale helps? Also modified the data into 'long' format which seems to be the preferred way for ggplot.


library(ggplot2)
library(tidyr)

stack.data |> 
  pivot_longer(-Date, values_to = "val", names_to = "ele")|> 
ggplot(aes(x = Date, y = val, colour = ele, group = ele)) +
  geom_line(size = 1.4) +
  scale_y_log10(labels = scales::comma)+
  scale_colour_manual(breaks = c("Mn", "Fe"),
                     values = c( "#F8766D", "#00BFC4")) +
  labs(colour = NULL,
       y = "Units")+
  theme_bw()+
  theme(legend.position="top",
        axis.text.x = element_text(size = 6))

data

stack.data <- structure(list(Date = c("2013-01-13", "2014-01-13", "2015-01-13", 
                                      "2016-01-13", "2017-01-13", "2018-01-13", "2019-01-13", "2020-01-13", 
                                      "2021-01-13", "2022-01-13"), 
                             Mn = c(67.7, 60.8, 57.1, 40.8, 30.8, 50.3, 20.8, 43.1, 53.8, 33.1), 
                             Fe = c(1990L, 2082L, 3901L, 7022L, 5063L, 2032L, 6225L, 8853L, 4048L, 6238L)), 
                        class = "data.frame", row.names = c(NA, -10L))

Created on 2022-10-13 with reprex v2.0.2

Peter
  • 11,500
  • 5
  • 21
  • 31
  • 1
    I would highly recommend this solution over any workaround that uses multiple y-axes. It emphasizes the different magnitudes of Mn versus Fe in a non-arbitrary way. – qdread Oct 13 '22 at 18:08
0

For completeness, to add a secondary axis you need to scale the data then add the secondary axis with the reverse transformation:

library(ggplot2)

ggplot(data = stack.data, aes(x = Date)) +
  geom_line(aes (y = Mn, color = "Mn"),  size = 1.4) +
  geom_line(aes (y = Fe / 100, color = "Fe"), size = 1.4) +
  scale_y_continuous(name = "Mn",
                     sec.axis = sec_axis(trans = ~ . * 100, name = "Fe"))+
  scale_color_manual("", values = c("#F8766D", "#00BFC4")) +
  theme_bw() +
  theme(legend.position = "top")

An alternative to this, and to the log scale, is to use facets with a free y scale:

ggplot(data = tidyr::pivot_longer(stack.data, -Date), aes(x = Date)) +
  geom_line(aes (y = value, color = name),  size = 1.4) +
  scale_y_continuous(name = "concentration") +
  scale_color_manual(NULL, values = c("#F8766D", "#00BFC4")) +
  facet_grid(name~., scales = "free_y") +
  theme_bw() +
  theme(legend.position = "top")

Created on 2022-10-13 with reprex v2.0.2

Allan Cameron
  • 147,086
  • 7
  • 49
  • 87