Skip to content

Instantly share code, notes, and snippets.

@tchakravarty
Last active August 18, 2016 09:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tchakravarty/d4ead37873dbf356df1ce2954e3d3f8d to your computer and use it in GitHub Desktop.
Save tchakravarty/d4ead37873dbf356df1ce2954e3d3f8d to your computer and use it in GitHub Desktop.
Dual Y-Axis ggplot2
library(ggplot2)
library(grid)
library(tidyr)
library(gtable)
library(dplyr)
gg_foo3_colors = c("#F8766D", "#00BFC4")
df_foo = read.csv(text = ",Russia,World
1996,0,423
1997,4,220
1998,1,221
1999,0,298
2000,0,322
2001,8,530
2002,6,466
2003,17,459
2004,25,562
2005,27,664
2006,33,760
2007,53,893
2008,87,1038
2009,32,761
2010,62,949
2011,101,1109
2012,96,1130
2013,110,1317
2014,111,1535
2015,88,1738") %>%
gather(key = Country, value = Value, -X) %>%
rename(Year = X)
#==========================================================
# create the individual plots
#==========================================================
#================================================
# Russia
#================================================
gg_russia = df_foo %>%
filter(Country == "Russia") %>%
ggplot(aes(x = Year, y = Value)) +
geom_line(color = gg_foo3_colors[[1]], size = 1.5) +
labs(x = NULL, y = NULL) +
# ggtitle("Russia") +
scale_x_continuous(breaks = c(1996, seq(2000, 2015, 5))) +
scale_y_continuous(expand = c(0, 0), limits = c(-0.9, 200.9)) +
theme_bw() +
theme(
# panel related theme elements
panel.border = element_blank(),
panel.background = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray50", size = 0.5),
panel.grid.major.x = element_blank(),
# axis text
axis.text.y = element_text(color = gg_foo3_colors[[1]], size = 12),
axis.text.x = element_text(size = 12),
# axis ticks
axis.ticks.x = element_line(),
axis.ticks.y = element_line(),
# axis ticks
axis.ticks = element_line(colour = "gray50"),
axis.ticks.length = unit(x = 0.25, units = "cm"),
axis.ticks.y = element_blank(),
# title
plot.title = element_text(hjust = 0.85, vjust = 2.12, color = gg_foo3_colors[[1]], size = 12)
)
# plot it
# gg_russia
#================================================
# Rest of the world
#================================================
gg_world = df_foo %>%
filter(Country == "World") %>%
ggplot(aes(x = Year, y = Value)) +
geom_line(color = gg_foo3_colors[[2]], size = 1.5) +
labs(x = NULL, y = NULL) +
# ggtitle("Rest of the World") +
scale_x_continuous(breaks = c(1996, seq(2000, 2015, 5))) +
scale_y_continuous(expand = c(0, 0), limits = c(-0.9, 2000.9)) +
theme_bw() +
theme(
# panel related theme elements
panel.border = element_blank(),
panel.background = element_blank(),
panel.grid.minor = element_blank(),
panel.grid.major = element_line(color = "gray50", size = 0.5),
panel.grid.major.x = element_blank(),
# axis text
axis.text.y = element_text(color = gg_foo3_colors[[2]], size = 12),
axis.text.x = element_text(size = 12),
# axis ticks
axis.ticks.x = element_line(),
axis.ticks.y = element_line(),
# axis ticks
axis.ticks = element_line(colour = "gray50"),
axis.ticks.length = unit(x = 0.25, units = "cm"),
axis.ticks.y = element_blank(),
# title
plot.title = element_text(hjust = -0.0135, vjust = 2.12, color = gg_foo3_colors[[2]], size = 12)
)
# plot it
# gg_world
#==========================================================
# combine the two plots
#==========================================================
# first override the titles
gg_russia = gg_russia
gg_world = gg_world
# then convert them to grobs
grob_russia = ggplotGrob(gg_russia)
grob_world = ggplotGrob(gg_world)
# 1. get the locations of the plot panels in the first plot
grob_panel_all = c(subset(ggplotGrob(gg_russia)$layout, name == "panel", se = t:r))
grob_russia = gtable_add_grob(
x = grob_russia,
grobs = grob_world$grobs[[which(grob_world$layout$name == "panel")]],
t = grob_panel_all$t,
l = grob_panel_all$l,
b = grob_panel_all$b,
r = grob_panel_all$l
)
# source the function that switches the grob orientation
source("https://raw.githubusercontent.com/wilkelab/cowplot/master/R/switch_axis.R")
# 2. get the y-axis from gg_world
yaxis = grob_world$grobs[[which(grob_world$layout$name == "axis-l")]]
# 3. reverse the ticks (tick marks, axis line and the tick labels) of the second y-axis
ticks.y = yaxis$children[[2]]
ticks.y$widths = rev(ticks.y$widths)
ticks.y$grobs = rev(ticks.y$grobs)
# 4. change the tick marks
# NOTE: not clear what has happened here
tml = plot_theme(gg_russia)$axis.ticks.length
ticks.y$grobs[[1]]$x = ticks.y$grobs[[1]]$x - unit(1, "npc") + tml
# 5. swap margins and fix justifications for the tick mark labels
ticks.y$grobs[[2]] = hinvert_title_grob(ticks.y$grobs[[2]])
# 6. put ticks back into the y-axis
yaxis$children[[2]] = ticks.y
# 7. put the transformed y-axis on the right side of grob_russia
grob_russia = gtable_add_cols(
grob_russia,
grob_world$widths[grob_world$layout[which(grob_world$layout$name == "axis-l"), ]$l],
grob_panel_all$r
)
# add the other y-axis to the plot
grob_russia = gtable_add_grob(
grob_russia,
yaxis,
grob_panel_all$t,
grob_panel_all$r + 1,
grob_panel_all$b,
grob_panel_all$r + 1,
clip = "off",
name = "axis-r"
)
# 8. create the labels for the top of the plot
left = textGrob(
"Russia",
x = 0,
y = 0.9,
just = c("left", "top"),
gp = gpar(fontsize = 12, col = gg_foo3_colors[[1]])
)
right = textGrob(
"Rest of the World",
x = 1,
y = 0.9,
just = c("right", "top"),
gp = gpar(fontsize = 12, col = gg_foo3_colors[[2]])
)
# put them together
labs = gTree("Labs", children = gList(left, right))
# 9. new row in the plot for the labels
height = unit(3, "grobheight", left)
gg_russia = gtable_add_rows(grob_russia, height, 2)
# put the label in the new row
grob_russia = gtable_add_grob(grob_russia, labs, t = 3, l = 3, r = 5)
grob_russia$layout[which(grob_russia$layout$name == "panel"), ]$clip = "off"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment