The cowplot package defines a function switch_axis_position()
that allows us to take the x and/or y axis of a plot and copy or move it to the other side of the plot (y axis to right, x axis to top). Here are some examples of moving or copying various axes. As we can see, this works regardless of the chosen theme.
Importantly, the return object is a gtable, not a ggplot object, so we need to feed it into ggdraw()
to display in the usual manner or to save with ggsave()
or save_plot()
.
require(cowplot)
require(grid) # for unit()
theme_set(theme_cowplot(font_size=12)) # reduce default font size
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = "blue")
ggdraw(switch_axis_position(p1 + theme_gray(), axis = 'y'))
ggdraw(switch_axis_position(p1 + theme_bw(), axis = 'x', keep = 'x'))
ggdraw(switch_axis_position(p1, axis = 'xy', keep = 'xy'))
ggdraw(switch_axis_position(p1 + theme(axis.ticks.length = unit(0.3, "cm"),
axis.text.x = element_text(margin = margin(0.2, unit = "cm"))), axis = 'xy'))
Moving the axes also works if there is a legend. What is not currently implemented, however, is moving axes on faceted plots.
p2 <- ggplot(diamonds, aes(clarity, fill = cut)) + geom_bar() +
theme(axis.text.x = element_text(angle = 70, vjust = 0.5))
ggdraw(switch_axis_position(p2, axis = 'x'))
When rotating text, you may need to fidle with hjust
and vjust
to get the labels to be correctly justified.
mtcars2 <- mtcars[1:15, ]
mtcars2$name <- row.names(mtcars2)
p3 <- ggplot(mtcars2, aes(x = name, y = mpg, fill = name)) +
geom_bar(stat = 'identity', position = "identity") +
scale_y_reverse() +
guides(fill = FALSE) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
ggdraw(switch_axis_position(p3, axis = 'x'))
In combination with some clever gtable manipulations, we can also align multiple plots with axes that have been switched. Note that the function gtable_squash_rows()
I’m using here is one of a few functions cowplot defines for manipulating gtables.
require(gtable)
# top plot
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_line(colour = 'blue') +
background_grid(minor = 'none')
g1 <- switch_axis_position(p1, 'xy') # switch both axes
g1 <- gtable_squash_rows(g1, length(g1$height)) # set bottom row to 0 height
p2 <- ggplot(mtcars, aes(mpg, qsec)) + geom_line(colour = 'green') + ylim(14, 25) +
background_grid(minor = 'none')
g2 <- ggplotGrob(p2)
g2 <- gtable_add_cols(g2, g1$widths[5:6], 4) # add the two additional columns that g1 has
g2 <- gtable_squash_rows(g2, 1:2) # set top two rows to 0 height
plot_grid(g1, g2, ncol = 1, align = 'v')