This post describes how to build a dual Y axis chart using
`R` and `ggplot2`. It uses the
`sec.axis` attribute to add the second Y axis. Note that
this kind of chart has major
drawbacks.
Use it with care.

`Rand`
`ggplot2`

Let’s consider a dataset with 3 columns:

`date`
`temperature. Range from 0 to 10.`
`price. Rangee from 0 to 100.`

One could easily build 2 line charts to study the evolution of those 2 series using the code below.

But even if strongly unadvised, one sometimes wants to display both series on the same chart, thus needing a second Y axis.

`# Libraries library(ggplot2) library(dplyr) library(patchwork) # To display 2 charts together library(hrbrthemes) # Build dummy data data <- data.frame( day = as.Date("2019-01-01") + 0:99, temperature = runif(100) + seq(1,100)^2.5 / 10000, price = runif(100) + seq(100,1)^1.5 / 10 ) # Most basic line chart p1 <- ggplot(data, aes(x=day, y=temperature)) + geom_line(color="#69b3a2", size=2) + ggtitle("Temperature: range 1-10") + theme_ipsum() p2 <- ggplot(data, aes(x=day, y=price)) + geom_line(color="grey",size=2) + ggtitle("Price: range 1-100") + theme_ipsum() # Display both charts side by side thanks to the patchwork package p1 + p2`

`sec.axis(): the idea`

`sec.axis()` does not allow to build an entirely new Y
axis. It just builds a second Y axis based on the first one,
applying a mathematical transformation.

In the example below, the second Y axis simply represents the first
one multiplied by 10, thanks to the `trans` argument that
provides the `~.*10` mathematical statement.

Note that because of that you can’t easily control the second axis lower and upper boundaries. We’ll see a trick below in the tweaking section.

`# Start with a usual ggplot2 call: ggplot(data, aes(x=day, y=temperature)) + # Custom the Y scales: scale_y_continuous( # Features of the first axis name = "First Axis", # Add a second axis and specify its features sec.axis = sec_axis( trans=~.*10, name="Second Axis") ) + theme_ipsum()`

`sec.axis()`

We can use this `sec.axis` mathematical transformation to
display 2 series that have a different range.

Since the price has a maximum value that is 10 times biggeer than the maximum temperature:

`trans=~.*10).`
`geom_line()call must be divided by 10 to mimic the range of the first variable.`

`# Value used to transform the data coeff <- 10 ggplot(data, aes(x=day)) + geom_line( aes(y=temperature)) + geom_line( aes(y=price / coeff)) + # Divide by 10 to get the same range than the temperature scale_y_continuous( # Features of the first axis name = "First Axis", # Add a second axis and specify its features sec.axis = sec_axis(~.*coeff, name="Second Axis") )`

`ggplot2`

A feew usual tricks to make the chart looks better:

`ipsumtheme to remove the black background and improve the general style`

`# Value used to transform the data coeff <- 10 # A few constants temperatureColor <- "#69b3a2" priceColor <- rgb(0.2, 0.6, 0.9, 1) ggplot(data, aes(x=day)) + geom_line( aes(y=temperature), size=2, color=temperatureColor) + geom_line( aes(y=price / coeff), size=2, color=priceColor) + scale_y_continuous( # Features of the first axis name = "Temperature (Celsius °)", # Add a second axis and specify its features sec.axis = sec_axis(~.*coeff, name="Price (\$)") ) + theme_ipsum() + theme( axis.title.y = element_text(color = temperatureColor, size=13), axis.title.y.right = element_text(color = priceColor, size=13) ) + ggtitle("Temperature down, price up")`

It is totally possible to usee the same tricks with other
`geoms`.

Here is an example displaying a line chart on top of a barplot.

`# Value used to transform the data coeff <- 10 # A few constants temperatureColor <- "#69b3a2" priceColor <- rgb(0.2, 0.6, 0.9, 1) ggplot(head(data, 80), aes(x=day)) + geom_bar( aes(y=temperature), stat="identity", size=.1, fill=temperatureColor, color="black", alpha=.4) + geom_line( aes(y=price / coeff), size=2, color=priceColor) + scale_y_continuous( # Features of the first axis name = "Temperature (Celsius °)", # Add a second axis and specify its features sec.axis = sec_axis(~.*coeff, name="Price (\$)") ) + theme_ipsum() + theme( axis.title.y = element_text(color = temperatureColor, size=13), axis.title.y.right = element_text(color = priceColor, size=13) ) + ggtitle("Temperature down, price up")`

You are watching: Dual Y axis with R and ggplot2. Info created by GBee English Center selection and synthesis along with other related topics.