3

I'm trying to create a ggplot2 graph showing a bar graph and a line graph overlaying each other. In excel this would be done by adding a second axis.

The x axis represents product type, the y values of the bar graph should represent revenue, and the line graph I want to represent profit margin as a percentage. The value of the line graph and the bar chart should be independent of each other, i.e. there is no such relationship.

require(ggplot2)    
df <- data.frame(x = c(1:5), y = abs(rnorm(5)*100))
df$y2 <- abs(rnorm(5))

ggplot(df, mapping= aes(x=as.factor(`x`), y = `y`)) + 
  geom_col(aes(x=as.factor(`x`), y = `y`),fill = 'blue')+
  geom_line(mapping= aes(x=as.factor(`x`), y = `y`),group=1) +
  geom_label(aes(label= round(y2,2))) +
  scale_y_continuous() +
  theme_bw() + 
  theme(axis.text.x = element_text(angle = 20,hjust=1)) 

enter image description here

The image above produces almost what I want. However, the scaling is incorrect - I would need the 1.38 and 0.23 value to be ordered by magnitude, i.e. the point 0.23 should show below 1.38. I am also not sure how to add another axsis on the right hand side.

M--
  • 25,431
  • 8
  • 61
  • 93
user33484
  • 740
  • 2
  • 9
  • 36
  • These type of graphs with two axis scales are usually frowned upon as bad practice: see [here](https://stackoverflow.com/questions/3099219/plot-with-2-y-axes-one-y-axis-on-the-left-and-another-y-axis-on-the-right) and [here](https://stackoverflow.com/questions/49185583/two-y-axes-with-different-scales-for-two-datasets-in-ggplot2). – Nautica Dec 24 '18 at 11:53
  • @VY - I think they're quite useful and especially for this it is quite easy to read and not misleading. Is there no way to get this achieved? – user33484 Dec 24 '18 at 11:59

1 Answers1

5

Starting with version 2.2.0 of ggplot2, it is possible to add a secondary axis - see this detailed demo. Also, some already answered questions with this approach: here, here, here or here. An interesting discussion about adding a second OY axis here.

The main idea is that one needs to apply a transformation for the second OY axis. In the example below, the transformation factor is the ratio between the max values of each OY axis.

# Prepare data
library(ggplot2)
set.seed(2018)
df <- data.frame(x = c(1:5), y = abs(rnorm(5)*100))
df$y2 <- abs(rnorm(5))

# The transformation factor
transf_fact <- max(df$y)/max(df$y2)

# Plot
ggplot(data = df,
       mapping = aes(x = as.factor(x),
                     y = y)) +
  geom_col(fill = 'blue') +
  # Apply the factor on values appearing on second OY axis
  geom_line(aes(y = transf_fact * y2), group = 1) +
  # Add second OY axis; note the transformation back (division)
  scale_y_continuous(sec.axis = sec_axis(trans = ~ . / transf_fact, 
                                         name = "Second axis")) +
  geom_label(aes(y = transf_fact * y2,
                 label = round(y2, 2))) +
  theme_bw() + 
  theme(axis.text.x = element_text(angle = 20, hjust = 1))

enter image description here

But if you have a particular wish for the one-to-one transformation, like, say value 100 from Y1 should correspond to value 1 from Y2 (200 to 2 and so on), then change the transformation (multiplication) factor to 100 (100/1): transf_fact <- 100/1 and you get this:

enter image description here

The advantage of transf_fact <- max(df$y)/max(df$y2) is using the plotting area in a optimum way when using two different scales - try something like transf_fact <- 1000/1 and I think you'll get the idea.

Valentin_Ștefan
  • 6,130
  • 2
  • 45
  • 68
  • Hi, thanks for your answer. Could you explain what you mean by the transformation factor? How did you think of using that particular one? – user33484 Dec 24 '18 at 14:37
  • Is just a constant that you use to multiply the values from one scale to transform then to another scale. Is a one-to-one transformation as required by `sec_axis` (see `?sec_axis`). [Here](https://rpubs.com/MarkusLoew/226759) is another demo. You can try other values for the factor, not only the max(y1)/max(y2) ratio (this one was sure to work for a fast example). – Valentin_Ștefan Dec 24 '18 at 14:56
  • I updated my answer, adding an extra example, that maybe clarifies the importance of the transformation/multiplication factor. – Valentin_Ștefan Dec 24 '18 at 15:26
  • Thanks Valentin, this was very helpful! I'm glad that it's possible to do this as I'm trying to recreate some of our excel features in R and one of them was graphs such as this – user33484 Dec 24 '18 at 15:46