Search code examples
rggplot2patchwork

Patchwork not aligning x axis with ggbreak


I was able to use patchwork to align two xaxis, but when I add ggbreak::scale_break(), it no longer aligns. What am I doing wrong here? Code of alignment issues follows. UnComment out scale_break() lines to see difference.

library(scales)
library(ggplot2)
library(ggbreak)
library(patchwork)

y <- as_tibble(c(rnorm(400,100,25),250) )
n= nrow(y)
cor = n/100
a.mean = mean(y$value)
a.median= quantile(y$value,0.5)
a.sd = sd(y$value)
binwidth = 5
upper.limit <-  260

plt1 <-ggplot(y, aes(x="", y = value) ) +
  geom_boxplot(fill = "lightblue", color = "black", outlier.shape=NA) +
  stat_boxplot(geom='errorbar',coef=NULL) +
  stat_summary(fun=mean, geom="point", shape=23, size=7.6, color="black", fill = "blue")  +
  coord_flip() +
  theme_classic() +
  theme(panel.border = element_rect(color="black", fill = NA, size = 1),
        axis.text = element_text(size=14)) +
  xlab("") +
  ylab("Value ($)") +
  #scale_y_break(c(200,240 ) ) +
  scale_y_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
  theme(axis.text.y=element_blank(),
        axis.ticks.y=element_blank(),
        axis.text.x.top=element_blank(),
        axis.ticks.x.top=element_blank() )

plt2 <- ggplot(y, aes(x = value) ) +
  geom_histogram(aes(y = (..count..)/sum(..count..)*100 ),
                 position = "identity", binwidth = 5,
                 fill = "lightblue", color = "black") +
  stat_function(fun = function(x)
    dnorm(x, mean = a.mean, sd = a.sd) * n * binwidth / cor,
    color="darkblue", size =1) +
  ylab("Percentage") +
  xlab("") +
  #scale_x_break(c(200,240 ) ) +
  scale_x_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
  scale_y_continuous(breaks=seq(0,15, by=2.5)) +
  theme(panel.border = element_rect(color="black", fill = NA, size = 1),
        plot.title = element_text(hjust = 0.5),
        text=element_text(size=20),
        axis.text = element_text(size=14),
        axis.text.x.top=element_blank(),
        axis.ticks.x.top=element_blank() )

Fig01_01 <- plt2 / plt1 + plot_layout(nrow = 2, heights = c(10, 2) )
Fig01_01

Solution

  • One solution might be to manually/invisibly add in the y-axis labels and ticks for the bottom plot as exactly the same size as the upper plot. ggbreak does additionally seem to add in an immovable margin around the whole plotting area, so you may have some extra white space between plots doing it this way:

    library(scales)
    library(tidyverse)
    library(ggbreak)
    library(patchwork)
    
    y <- as_tibble(c(rnorm(400,100,25),250) )
    n= nrow(y)
    cor = n/100
    a.mean = mean(y$value)
    a.median= quantile(y$value,0.5)
    a.sd = sd(y$value)
    binwidth = 5
    upper.limit <-  260
    
    plt1 <-ggplot(y, aes(x=1, y = value) ) +
      geom_boxplot(fill = "lightblue", color = "black", outlier.shape=NA) +
      stat_boxplot(geom='errorbar',coef=NULL) +
      stat_summary(fun=mean, geom="point", shape=23, size=7.6, color="black", fill = "blue")  +
      coord_flip() +
      theme_classic() +
      theme(panel.border = element_rect(color="black", fill = NA, size = 1),
            axis.text = element_text(size=14)) +
      xlab(" ") +
      ylab("Value ($)") +
      scale_y_break(c(200,240 ) ) +
      scale_y_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
      theme(axis.text.y=element_text(colour = "white", size = 14),
            axis.ticks.y=element_line(colour = "white"),
            axis.text.x.top=element_blank(),
            axis.title.y=element_text(size=20),
            axis.ticks.x.top=element_blank() )
    
    plt2 <- ggplot(y, aes(x = value) ) +
      geom_histogram(aes(y = (..count..)/sum(..count..)*100 ),
                     position = "identity", binwidth = 5,
                     fill = "lightblue", color = "black") +
      stat_function(fun = function(x)
        dnorm(x, mean = a.mean, sd = a.sd) * n * binwidth / cor,
        color="darkblue", size =1) +
      ylab("Percentage") +
      xlab("") +
      scale_x_break(c(200,240 ) ) +
      scale_x_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
      scale_y_continuous(breaks=seq(0,15, by=2.5)) +
      theme(panel.border = element_rect(color="black", fill = NA, size = 1),
            plot.title = element_text(hjust = 0.5),
            text=element_text(size=20),
            axis.text = element_text(size=14),
            axis.text.x.top=element_blank(),
            axis.ticks.x.top=element_blank() )
    
    Fig01_01 <- plt2 / plt1 + plot_layout(nrow = 2, heights = c(6, 2) )
    Fig01_01