rggplot2ggpubr

Unable to align x-axis ticks using ggarrange


I am creating two graphs that use the same dataset and date range, though the top graph shows total specimens per month and the bottom shows typed and untyped specimens by year. Because of the grouping by year/month they xaxis ticks don't align and I don't know of a clean way to do this, though I am really interested to learn how to do this properly as its something I will be doing frequently.

Currently using ggarrange to create this figure: enter image description here

Using the following code:

## reproducible example ##

> dput(Total)
structure(list(MonthStart = c("01/01/2015", "01/02/2015", "01/03/2015", 
"01/04/2015", "01/05/2015", "01/06/2015", "01/07/2015", "01/08/2015", 
"01/09/2015", "01/10/2015", "01/11/2015", "01/12/2015", "01/01/2016", 
"01/02/2016", "01/03/2016", "01/04/2016", "01/05/2016", "01/06/2016", 
"01/07/2016", "01/08/2016", "01/09/2016", "01/10/2016", "01/11/2016", 
"01/12/2016", "01/01/2017", "01/02/2017", "01/03/2017", "01/04/2017", 
"01/05/2017", "01/06/2017", "01/07/2017", "01/08/2017", "01/09/2017", 
"01/10/2017", "01/11/2017", "01/12/2017", "01/01/2018", "01/02/2018", 
"01/03/2018", "01/04/2018", "01/05/2018", "01/06/2018", "01/07/2018", 
"01/08/2018", "01/09/2018", "01/10/2018", "01/11/2018", "01/12/2018", 
"01/01/2019", "01/02/2019", "01/03/2019", "01/04/2019", "01/05/2019", 
"01/06/2019", "01/07/2019", "01/08/2019", "01/09/2019", "01/10/2019", 
"01/11/2019", "01/12/2019", "01/01/2020", "01/02/2020", "01/03/2020", 
"01/04/2020", "01/05/2020", "01/06/2020", "01/07/2020", "01/10/2020", 
"01/11/2020", "01/12/2020", "01/01/2021", "01/02/2021", "01/03/2021", 
"01/04/2021", "01/05/2021", "01/06/2021", "01/07/2021", "01/08/2021", 
"01/09/2021", "01/10/2021", "01/11/2021", "01/12/2021", "01/01/2022", 
"01/02/2022", "01/03/2022", "01/04/2022", "01/05/2022", "01/06/2022", 
"01/07/2022", "01/08/2022", "01/09/2022", "01/10/2022", "01/11/2022", 
"01/12/2022", "01/01/2023", "01/02/2023", "01/03/2023", "01/04/2023", 
"01/05/2023", "01/06/2023", "01/07/2023", "01/08/2023", "01/09/2023", 
"01/10/2023", "01/11/2023", "01/12/2023", "01/01/2024", "01/02/2024", 
"01/03/2024", "01/04/2024", "01/05/2024"), Count = c(172.8, 187.2, 
136.8, 247.2, 141.6, 163.2, 379.2, 292.8, 228, 381.6, 537.6, 
504, 441.6, 350.4, 244.8, 172.8, 206.4, 316.8, 429.6, 439.2, 
345.6, 494.4, 489.6, 362.4, 237.6, 283.2, 496.8, 417.6, 424.8, 
633.6, 664.8, 290.4, 100.8, 194.4, 328.8, 261.6, 187.2, 252, 
211.2, 230.4, 278.4, 331.2, 350.4, 288, 187.2, 612, 616.8, 494.4, 
400.8, 225.6, 403.2, 403.2, 391.2, 278.4, 609.6, 532.8, 372, 
708, 631.2, 367.2, 343.2, 240, 172.8, 64.8, 28.8, 52.8, 2.4, 
14.4, 21.6, 16.8, 24, 12, 24, 33.6, 43.2, 60, 105.6, 146.4, 273.6, 
456, 660, 499.2, 448.8, 424.8, 518.4, 432, 372, 369.6, 340.8, 
381.6, 530.4, 904.8, 1084.8, 1456.8, 578.4, 849.6, 1068, 772.8, 
943.2, 883.2, 919.2, 799.2, 544.8, 945.6, 988.8, 868.8, 600, 
499.2, 732, 799.2, 141.6)), class = "data.frame", row.names = c(NA, 
-111L))

> dput(Positive)
structure(list(YearStart = c("01/01/2015", "01/01/2015", "01/01/2016", 
"01/01/2016", "01/01/2017", "01/01/2017", "01/01/2018", "01/01/2018", 
"01/01/2019", "01/01/2019", "01/01/2020", "01/01/2020", "01/01/2021", 
"01/01/2021", "01/01/2022", "01/01/2022", "01/01/2023", "01/01/2023", 
"01/01/2024", "01/01/2024"), Typable = c("Typed", "Untyped", 
"Typed", "Untyped", "Typed", "Untyped", "Typed", "Untyped", "Typed", 
"Untyped", "Typed", "Untyped", "Typed", "Untyped", "Typed", "Untyped", 
"Typed", "Untyped", "Typed", "Untyped"), Count = c(1240.8, 445.2, 
1327.2, 819.6, 1261.2, 906, 1758, 261.6, 2241.6, 420, 416.4, 
62.4, 966, 202.8, 2808, 824.4, 3694.8, 1386, 1053.6, 332.4)), class = "data.frame", row.names = c(NA, 
-20L))

## plot ##

TotalPlot <- ggplot(Total, aes(x = MonthStart, y = Count)) +
  geom_bar(stat = "identity", fill = "grey10") +
  theme_bw() + 
  scale_x_date(breaks = "1 year",
               date_labels = "%Y")


Typable <- ggplot(Positive, aes(x = YearStart, y = Count, fill = Typable)) +
  geom_bar(stat = "identity", position = position_fill(reverse = TRUE)) +
  theme_bw() + 
  scale_x_date(breaks = "1 year",
               date_labels = "%Y")+
  scale_fill_manual(values = c("Typed" = "#AD2E24", "Untyped" = "#F1A66A"))
Typable

RatioFigure <- ggarrange(TotalPlot, Typable,
                         ncol = 1,
                         nrow = 2,
                         heights = c(1,2),
                         widths = c(1,1),
                         labels = c("A", "B"))
RatioFigure

Thanks for any help!


Solution

  • Couple of steps to make it align. Add missing months for each year, then show labels only for June, so it aligns with "B" bars.

    # convert to date, in reproducible data it was character.
    Total$MonthStart <- as.Date(Total$MonthStart, "%d/%m/%Y")
    Positive$YearStart <- as.Date(Positive$YearStart, "%d/%m/%Y")
    
    # add missing months with zero Counts.
    TotalC <- Total %>%
      complete(MonthStart = seq(as.Date("2015-01-01"), as.Date("2024-12-01"), by = "month"),
               fill = list(Count = 0))
    
    TotalPlot <- ggplot(TotalC, aes(x = MonthStart, y = Count)) +
      geom_bar(stat = "identity", fill = "grey10") +
      theme_bw() + 
      #custom breaks to set to middle of the year = June
      scale_x_date(breaks = TotalC %>% 
                     filter(months(TotalC$MonthStart) == "June") %>% 
                     pull(MonthStart),
                   date_labels = "%Y")
    
    Typable <- ggplot(Positive, aes(x = YearStart, y = Count, fill = Typable)) +
      geom_bar(stat = "identity", position = position_fill(reverse = TRUE)) +
      theme_bw() + 
      scale_x_date(breaks = "1 year", date_labels = "%Y")+
      scale_fill_manual(values = c("Typed" = "#AD2E24", "Untyped" = "#F1A66A"))
    
    ggpubr::ggarrange(TotalPlot, Typable,
              ncol = 1,
              labels = c("A", "B"),
              align = "v")
    

    enter image description here