ggplot with 2 y axes on each side and different scales
Sometimes a client wants two y scales. Giving them the "flawed" speech is often pointless. But I do like the ggplot2 insistence on doing things the right way. I am sure that ggplot is in fact educating the average user about proper visualization techniques.
Maybe you can use faceting and scale free to compare the two data series? - e.g. look here: https://github.com/hadley/ggplot2/wiki/Align-two-plots-on-a-page
ggplot with 2 y axes on each side and different scales for different data
You should try this:
geom_line(aes(y = INJ*15, color = UWI))
You will get:
It is hard to distinguish 34 shades of color in my plot. Also, you can try multiplying by 10 or 20.
two y-axes with different scales for two datasets in ggplot2
Up front, this type of graph is a good example of why it took so long to get a second axis into ggplot2
: it can very easily be confusing, leading to mis-interpretations. As such, I'll go to pains here to provide multiple indicators of what goes where.
First, the use of sec_axis
requires a transformation on the original axis. This is typically done in the form of an intercept/slope formula such as ~ 2*. + 10
, where the period indicates the value to scale. In this case, I think we could get away with simply ~ 2*.
However, this implies that you need to plot all data on the original axis, meaning you need d2$y
to be pre-scaled to d1$y
's limits. Simple enough, you just need the reverse transformation as what will be used in sec_axis
.
I'm going to combine the data into a single data.frame, though, in order to use ggplot2
's grouping.
d1 = data.frame(x=c(100, 200, 300, 400), y=seq(0.1, 0.4, by=0.1)) # 1st dataset
d2 = data.frame(x=c(100, 200, 300, 400), y=seq(0.8, 0.5, by=-0.1)) # 2nd dataset
d1$z <- "data1"
d2$z <- "data2"
d3 <- within(d2, { y = y/2 })
d4 <- rbind(d1, d3)
d4
# x y z
# 1 100 0.10 data1
# 2 200 0.20 data1
# 3 300 0.30 data1
# 4 400 0.40 data1
# 5 100 0.40 data2
# 6 200 0.35 data2
# 7 300 0.30 data2
# 8 400 0.25 data2
In order to control color in all components, I'll set it manually:
mycolors <- c("data1"="blue", "data2"="red")
Finally, the plot:
library(ggplot2)
ggplot(d4, aes(x=x, y=y, group=z, color=z)) +
geom_path() +
geom_point() +
scale_y_continuous(name="data1", sec.axis = sec_axis(~ 2*., name="data2")) +
scale_color_manual(name="z", values = mycolors) +
theme(
axis.title.y = element_text(color = mycolors["data1"]),
axis.text.y = element_text(color = mycolors["data1"]),
axis.title.y.right = element_text(color = mycolors["data2"]),
axis.text.y.right = element_text(color = mycolors["data2"])
)
Frankly, though, I don't like the different slopes. That is, two blocks on the blue axis are 0.1, whereas on the red axis they are 0.2. If you're talking about two vastly different "things", then this may be fine. If, however, the slopes of the two lines are directly comparable, then you might prefer to keep the size of each block to be the same. For this, we'll use a transformation of just an intercept, no change in slope. That means the in-data.frame transformation could be y = y - 0.4
, and the plot complement ~ . + 0.4
, producing:
PS: hints taken from https://stackoverflow.com/a/45683665/3358272 and https://stackoverflow.com/a/6920045/3358272
How to draw dual y-axis in ggplot with different y ranges?
Does this do what you want?
ggplot2 is an opinionated framework, and one of those opinions is that secondary axes should be avoided. While it allows them, it requires some manual work from the user to put all series in terms of the main axis, and then allows a secondary axis as an annotation.
ggplot(data=data, aes(x = x)) +
geom_line(aes(y = y1), colour="red") +
geom_line(aes(y = y2 / 15), colour="blue") +
scale_y_continuous(sec.axis = ~.*15)+
theme(axis.text.y.left = element_text(color = "red"),
axis.text.y.right = element_text(color = "blue"))
Data on secondary axis in GGPlot
Thanks to the link provided, I was able to answer the question. The code here worked:
ggplot with 2 y axes on each side and different scales
R - How to plot ggplot2 with two y axes on different scales *with time variables
One approach would be to convert the time to decimal hours (or minutes, etc.) and adjust the scale labels:
library(dplyr); library(lubridate)
a %>%
# tidyr::gather(type, time, -date) %>%
tidyr::pivot_longer(-date, "type", "time") %>% # Preferred syntax since tidyr 1.0.0
mutate(time_dec = hour(value) + minute(value)/60 + second(value)/3600,
time_scaled = time_dec * if_else(type == "mile", 30, 1)) %>%
ggplot() +
geom_point(aes(x=date, y=time_scaled, group=value, color = type)) +
scale_y_continuous(breaks = 0:3,
labels = c("0", "1:00", "2:00", "3:00"),
name = "Marathon",
sec.axis = sec_axis(~./30,
name = "Mile",
breaks = (1/60)*0:100,
labels = 0:100)) +
expand_limits(y = c(1.5,3)) +
transition_reveal(date)
How to plot a second y axis for one category in the data?
The way to think about a secondary axis is that it is just an annotation. The actual data you are plotting needs to be transformed so it fits in the same scale as the rest of your data.
In your case, this means you need to divide all the c values by 100 to plot them, and draw a secondary axis that is transformed to show numbers 100 times larger:
ggplot(within(df.melt, value[variable == 'c'] <- value[variable == 'c']/100),
aes(xVal, value, colour = variable)) +
geom_point() +
geom_line() +
scale_y_continuous(sec.axis = sec_axis(~.x*100, name = "Values (c)")) +
theme(axis.text.y.right = element_text(color = "red"),
axis.ticks.y.right = element_line(color = "red"),
axis.title.y.right = element_text(color = "red"))
Related Topics
Remove Specific Characters from Column Names in R
Converting Data Frame into a List of Lists in R
How to Select Variables in an R Dataframe Whose Names Contain a Particular String
How to Generate the First N Terms in the Series:
Why Does Summarize or Mutate Not Work With Group_By When I Load 'Plyr' After 'Dplyr'
How to Remove All Duplicates So That None Are Left in a Data Frame
How to Assign Colors to Categorical Variables in Ggplot2 That Have Stable Mapping
Ggplot2 - Bar Plot With Both Stack and Dodge
Selecting Multiple Odd or Even Columns/Rows for Dataframe
How to Loop Through List and Create Separate Dataframes in R
Mapping Columns/Rows from One Dataframe to Another Based on Row Number
Plotting Two Variables as Lines Using Ggplot2 on the Same Graph
What Are the Differences Between "=" and "≪-" Assignment Operators