set ggplot plots to have same x-axis width and same space between dot plot rows

library(gridExtra)
library(grid)

gb1 <- ggplot_build(dat1.plot)
gb2 <- ggplot_build(dat2.plot)

# work out how many y breaks for each plot
n1 <- length(gb1$layout$panel_params[[1]]$y.labels)
n2 <- length(gb2$layout$panel_params[[1]]$y.labels)

gA <- ggplot_gtable(gb1)
gB <- ggplot_gtable(gb2)

g <- rbind(gA, gB)

# locate the panels in the gtable layout
panels <- g$layout$t[grepl("panel", g$layout$name)]
# assign new (relative) heights to the panels, based on the number of breaks
g$heights[panels] <- unit(c(n1,n2),"null")

grid.newpage()
grid.draw(g)

enter image description here


Here's one approach: fill in extra spaces for shorter labels and use a monospace font.

longest_name <- max(nchar(as.character(dat1$VARIABLES)), nchar(as.character(dat2$VARIABLES)))
fill_in_spaces <- function(v) paste0(paste0(rep(" ", longest_name - nchar(v)), collapse=""), v)
levels(dat1$VARIABLES) <- sapply(levels(dat1$VARIABLES), fill_in_spaces)
levels(dat2$VARIABLES) <- sapply(levels(dat2$VARIABLES), fill_in_spaces)

Then the plotting procedure is almost the same, just add

p <- p + theme(text=element_text(family="Courier", size=14))

enter image description here

There is a minor issue: levels are reordered, so Item 3 is now the last, but that can be easily fixed like described e.g. here.


dat1$Plot <- "Plot 1"
dat2$Plot <- "Plot 2"
dataset <- rbind(dat1, dat2)

ggplot(
  dataset, 
  aes(
    y = reorder(as.character(VARIABLES), est), 
    x = est,
    xmin = min,
    xmax = max
  )) +
  geom_errorbarh() + geom_point() + 
facet_wrap(~Plot, ncol = 1, scales = "free_y")

enter image description here