I am trying to combine two ggplot objects with patchwork
– two plots with different subsets of data, but the same x variable (and therefore same unit). I would like to align the plots according to the x values – Each x unit should have the same physical width in the final plot.
This is very easy when actually plotting the entire width of the larger data set (see plot below) – but I struggle to plot only parts of the data and keeping the same alignment.
library(ggplot2)
library(patchwork)
library(dplyr)
p1 <-
ggplot(mtcars, aes(mpg)) +
geom_density(trim = TRUE) +
scale_x_continuous(limits = c(10,35))
p2 <-
ggplot(filter(mtcars, mpg < 20), aes(mpg)) +
geom_histogram(binwidth = 1, boundary = 1) +
scale_x_continuous(limits = c(10,35))
p1/p2
Created on 2019-08-07 by the reprex package (v0.3.0)
The desired output
That’s photoshopped
adding coord_cartesian(xlim = c(10,(20 or 35)), clip = 'off')
, and/or changing scale_x
limits to c(0,(20 or 35))
doesn’t work.
patchwork
also won’t let me set the widths of both plots when they are in two rows, which makes sense in a way. So I could create an empty plot for the second row and set the widths for those, but this seems a terrible hack and I feel there must be a much easier solution.
I am not restricted to patchwork
, but any solution allowing to use it would be very welcome.
2
Answers
Here is an option with
grid.arrange
that does not use a blank plot, but requires a manual of adjustment of:Should make this plot:
I modified the
align_plots
function from the cowplot package for this, so that itsplot_grid
function can now support adjustments to the dimensions of each plot.(The main reason I went with cowplot rather than patchwork is that I haven’t had much tinkering experience with the latter, and overloading common operators like
+
makes me slightly nervous.)Demonstration of results
Plots in 1 column (x-axes aligned for 15-28 range):
Plots in 1 row (y-axes aligned for 1 – 3.5 range):
Caveats
This hack assumes the plots that the user intends to align (either horizontally or vertically) have reasonably similar axes of comparable magnitude. I haven’t tested it on more extreme cases.
This hack expects simple non-faceted plots in Cartesian coordinates. I’m not sure what one could expect from aligning faceted plots. Similarly, I’m not considering polar coordinates (what’s there to align?) or map projections (haven’t looked into this, but they feel rather complicated).
This hack expects the gtable cell containing the plot panel to be in the 7th row / 5th column of the gtable object, which is based on my understanding of how ggplot objects are typically converted to gtables, and may not survive changes to the underlying code.
Code
Modified version of
cowplot::align_plots
:Utilising the above modified function with cowplot package’s
plot_grid
:(Alternatively, we can define a modified version of
plot_grid
function that usesalign_plots_modified
instead ofcowplot::align_plots
. Results would be the same either way.)