Patchwork: A Powerful Library for Plot Composition

The patchwork library in R is a versatile tool designed to simplify the arrangement and combination of multiple ggplot2 plots into complex layouts. Introduced by Pedersen (2020), patchwork leverages an intuitive “+” operator, allowing users to effortlessly stack, align, or grid plots without requiring intricate code. This functionality is especially valuable in exploratory data analysis and publication-quality visualizations.

Compared to alternatives like cowplot or gridExtra, patchwork stands out due to its syntax simplicity and seamless integration with ggplot2. The library also supports advanced layout customization using plot_layout(), enabling nested plots and specific adjustments to column and row configurations (Wilke, 2019).

Widely adopted by data analysts, patchwork improves workflow efficiency by eliminating the need for manual layout designs. Moreover, its compatibility with other visualization tools underscores its adaptability in modern data science projects (Wickham et al., 2021).

R Codes

# https://github.com/Z3tt/TidyTuesday/blob/main/R/2019_24_Meteorites.Rmd

# Clear R environment: 
rm(list = ls())

# Load some R packages: 
library(ggplot2)
library(dplyr)
library(showtext)

color_bgr <- "#1d1330"
my_font <- "Roboto Mono"

font_add_google(my_font, my_font)
showtext_auto()

df_meteor <- readr::read_csv("https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2019/2019-06-11/meteorites.csv") 

df_meteor %>% 
  mutate(decade = year - year %% 10,
         century = year - year %% 100) -> df_meteor

df_meteor %>% 
  filter(decade >= 1500, fall == "Fell") %>% 
  group_by(decade) %>% 
  count() %>% 
  ungroup() -> df_line

df_line %>% 
  pull(n) %>% 
  mean() -> avg

df_line %>% 
  filter(decade == 2010) -> df2010

df_line %>% 
  ggplot(aes(x = decade, y = n)) + 
  theme(plot.background = element_rect(fill = color_bgr, color = NA)) + 
  theme(panel.background = element_rect(fill = color_bgr, color = NA)) +
  theme(panel.grid.minor = element_blank()) + 
  theme(panel.grid.major = element_line(linewidth = 0.01, colour = "#153915")) + 
  geom_line(size = 0.8, color = "green", alpha = 1) + 
  geom_ribbon(aes(ymin = -Inf, ymax = n), fill = "green", alpha = 0.15) + 
  geom_hline(aes(yintercept = avg), color = "green", linetype = "dashed") + 
  geom_point(data = df2010, color = "red", size = 15, alpha = 0.3) + 
  geom_point(data = df2010, color = "red", size = 6, alpha = 0.3) + 
  geom_point(data = df2010, color = "red", size = 1, alpha = 1) + 
  annotate("text", x = 1710, y = 85, 
           label = "WARNING!", color = "red", 
           family = my_font, size = 8, fontface = "bold") +
  annotate("text", x = 1710, y = 76, 
           label = "The number of fallen meteorites\nis drastically decreasing!", 
           color = "grey90", family = my_font, size = 3.5) +
  scale_x_continuous(expand = c(0, 0), breaks = seq(1500, 2050, by = 50), 
                     limits = c(1490, 2055)) +
  scale_y_continuous(expand = c(0,0), limits = c(-2, 100), 
                     breaks = seq(0, 100, by = 10)) + 
  theme(axis.text = element_text(color = "green", size = 9)) + 
  theme(plot.margin = unit(rep(0.5, 4), "cm")) -> fig1

fig1

df_meteor_prev <- df_meteor %>% 
  filter(fall == "Fell", 
         decade >= 1500, 
         decade < 2010)

df_meteor_now <- df_meteor %>% 
  filter(fall == "Fell", 
         decade == 2010)

df_meteor_heavy <- df_meteor %>% 
  filter(fall == "Fell", 
         decade >= 1500) %>% 
  mutate(group = case_when(decade == 2010 ~ "now", TRUE ~ "prev")) %>% 
  group_by(group) %>% 
  top_n(1, mass) %>% 
  mutate(name = glue::glue("> {name} ({year})"),
         class = glue::glue("> Class: {class}"),
         mass = glue::glue("> Mass: {mass / 1000} kg"))

map_data("world") -> df_world

df_world %>% 
  ggplot(aes(x = long, y = lat)) +
  theme(plot.background = element_rect(fill = color_bgr, color = NA)) + 
  theme(panel.background = element_rect(fill = color_bgr, color = NA)) +
  theme(panel.grid.minor = element_blank()) +  
  theme(panel.grid.major = element_line(linewidth = 0.01, colour = "#153915")) + 
  geom_polygon(aes(group = group), fill = "#001810", color = "#004e00") + 
  geom_point(data = df_meteor_prev, color = "green", size = 0.8, alpha = 0.35) +
  geom_point(data = df_meteor_now, color = "red", size = 9, alpha = 0.2) +
  geom_point(data = df_meteor_now, color = "red", size = 3.3, alpha = 0.5) +
  geom_point(data = df_meteor_now, color = "red", size = 1.5) + 
  geom_segment(data = df_meteor_heavy, 
               aes(x = long, xend = long, y = lat, yend = lat + 13.5), 
               color = "grey65", size = 0.5) +  
  geom_segment(data = df_meteor_heavy, 
               aes(x = long - 25.1, xend = long + 25.1, y = lat + 13.5, yend = lat + 13.5), 
               color = "grey65", size = 1.3) + 
  geom_text(data = df_meteor_heavy, aes(long - 23, lat + 28, label = name),
            family = my_font, color = "green", size = 2.7, fontface = "bold", hjust = 0) +
  geom_text(data = df_meteor_heavy, aes(long - 23, lat + 23, label = class), 
            family = my_font, color = "grey95", size = 2.7, fontface = "bold", hjust = 0) +
  geom_text(data = df_meteor_heavy, aes(long - 23, lat + 18, label = mass), 
            family = my_font, color = "grey95", size = 2.7, fontface = "bold", hjust = 0) +
  annotate("text", x = -169, y = -28, label = "Please Enter Password for User 'NASA1'", 
           color = "grey95", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -33, label = "> TRUMP123456", 
           color = "green", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -38, label = "Welcome Mr. President!", 
           color = "grey95", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -43, label = "> MapView.Basic(MeteoritesV19.06.12)", 
           color = "green", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -48, label = "Processing: |||||||||||||||||||| 100%", 
           color = "grey95", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -53, label = "Map `MeteoritesV19.06.12` loaded.", 
           color = "grey95", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -58, label = "> MapView.Highlight(MeteoritesV19.06.12$recent)", 
           color = "green", family = my_font, size = 2.8, hjust = 0) +
  annotate("text", x = -169, y = -63, label = "Processing: |||||||||||||| 73.4%", 
           color = "grey95", family = my_font, size = 2.8, hjust = 0) +
  scale_x_continuous(breaks = seq(-200, 200, by = 25), expand = c(0, 0)) +
  scale_y_continuous(breaks = seq(-100, 100, by = 25)) +
  scale_size_continuous(range = c(0.25, 1)) + 
  theme(axis.text = element_blank()) +  
  labs(title = "Meteorite Landings", 
       subtitle = "The dataset for this map, derived from publicly available NASA data, includes the location,\nmass, composition, and fall year of over 45,000 meteorites that have struck Earth.", 
       caption = "Data Source: National Aeronautics and Space Administration (NASA)") + 
  theme(plot.caption = element_text(color = "grey75", family = my_font, size = 9)) + 
  theme(plot.title = element_text(size = 18, family = my_font, color = "green", face = "bold")) + 
  theme(plot.subtitle = element_text(size = 10, family = my_font, color = "white")) + 
  theme(plot.margin = unit(rep(0.5, 4), "cm")) -> fig2 

 
fig2  

References

  1. Pedersen, T.L. (2020). patchwork: The Composer of Plots. Available at: https://github.com/thomasp85/patchwork.
  2. Wilke, C. (2019). Cowplot: Streamlined Plot Theme and Plot Annotations for ggplot2. CRAN. Available at: https://cran.r-project.org/package=cowplot.
  3. Wickham, H., Chang, W., Henry, L., et al. (2021). ggplot2: Elegant Graphics for Data Analysis. Springer. Available at: https://ggplot2.tidyverse.org.