I am combining two distinct plots into a grid layout with grid
as suggested by @lgautier in rpy2 using python. The top plot is a density and and the bottom a ba
Aligning two plots becomes much trickier when facets are involved. I don't know if there is a general solution, even in R. Consider this scenario,
p1 <- ggplot(mtcars, aes(mpg, wt)) + geom_point() +
facet_wrap(~ cyl, ncol=2,scales="free")
p2 <- p1 + facet_null() + aes(colour=am) + ylab("this\nis taller")
gridExtra::grid.arrange(p1, p2)
With some work, you can compare the widths for the left axis, and the legends (which may or may not be present on the right side).
library(gtable)
# legend, if it exists, may be the second last item on the right,
# unless it's not on the right side.
locate_guide <- function(g){
right <- max(g$layout$r)
gg <- subset(g$layout, (grepl("guide", g$layout$name) & r == right - 1L) |
r == right)
sort(gg$r)
}
compare_left <- function(g1, g2){
w1 <- g1$widths[1:3]
w2 <- g2$widths[1:3]
unit.pmax(w1, w2)
}
align_lr <- function(g1, g2){
# align the left side
left <- compare_left(g1, g2)
g1$widths[1:3] <- g2$widths[1:3] <- left
# now deal with the right side
gl1 <- locate_guide(g1)
gl2 <- locate_guide(g2)
if(length(gl1) < length(gl2)){
g1$widths[[gl1]] <- max(g1$widths[gl1], g2$widths[gl2[2]]) +
g2$widths[gl2[1]]
}
if(length(gl2) < length(gl1)){
g2$widths[[gl2]] <- max(g2$widths[gl2], g1$widths[gl1[2]]) +
g1$widths[gl1[1]]
}
if(length(gl1) == length(gl2)){
g1$widths[[gl1]] <- g2$widths[[gl2]] <- unit.pmax(g1$widths[gl1], g2$widths[gl2])
}
grid.arrange(g1, g2)
}
align_lr(g1, g2)
Note that I haven't tested other cases; I'm sure it's very easy to break. As far as I understand from the docs, rpy2
provides a mechanism to use an arbitrary piece of R code, so the conversion should not be a problem.