Search code examples
rggplot2cowplot

How to arrange multiple plots in using cowplot and ggplot


Edit: added image for reference
https://prnt.sc/Lm5Kk9phys7i

I have two plots that I am trying to combine into one image and then add additional texts. I am trying to:

  1. Add a blue background to the title bar
  2. Add a paragraph of text above each plot (two blocks of text - one above each individual plot title)

I would prefer the solution to look nice in RMarkdown html output, but a .png would be fine as well.

library(tidyverse)
library(ggrepel)
library(ggtext)
library(lubridate)
library(scales)
library(cowplot)

#plot 1 data
date <- as.Date(c("2019-09-01","2019-10-01","2019-11-01","2019-12-01",
                  "2020-01-01","2020-02-01","2020-03-01","2020-04-01"))
year <- c(2019,2019,2019,2019,2020,2020,2020,2020)
month <- c("Sep", "Oct", "Nov", "Dec", "Jan", "Feb", "Mar", "Apr")
sales <- c(100,200,600,200,100,100,800,100)
df <- data.frame(date,year,month,sales)
df <- add_row(df, date = as.Date("2019-08-15"), year = 2019, month = "Aug", sales = NA)
df <- add_row(df, date = as.Date("2020-04-15"), year = 2020, month = "Apr", sales = NA)
df <- df %>% arrange(date)

#plot 1 without facet years
data_start <- df %>% filter(row_number()==2)
data_mid <- df %>% filter(row_number()==5)
data_end <- df %>% filter(row_number()==9)

p1 <- ggplot(df, aes(x = date, y = sales)) +
  geom_line() +
  scale_x_date(
    date_labels = "%b",
    date_breaks = "month", 
    expand = c(0, 0)) +
  theme_bw() +
  theme(
    strip.placement = "outside",
    strip.background = element_rect(fill = NA, colour = NA),
    panel.spacing = unit(0, "lines"),
    axis.line = element_line(colour = "gray"),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    panel.border = element_blank(),
    panel.background = element_blank(),
    axis.title.x = element_text(colour = "gray"),
    axis.title.y = element_text(hjust=1, colour = "gray"),
    axis.text.x = element_text(colour = "gray"),
    axis.text.y = element_text(colour = "gray"),
    strip.text.x = element_text(colour = "gray", size = 9),
    plot.title = element_markdown(size = 14),
    plot.subtitle = element_text(size=10, colour = "#818589"),
    plot.margin = margin(0,0,0,0, "cm")) + #margins: (top,right,bottom,left)
  geom_point(data_start, mapping=aes(x=date,y=sales), colour="blue", size=2) +
  geom_point(data_mid, mapping=aes(x=date,y=sales), colour="blue", size=2) +
  geom_point(data_end, mapping=aes(x=date,y=sales), colour="blue", size=2) +
  geom_text(data=subset(df, year == 2019 & month == "Sep"), 
            aes(date,sales,label=sales),
            position = position_dodge(width = 1),
            vjust = -1, hjust=1,size = 5) +
  geom_text(data=subset(df, year == 2019 & month == "Dec"), 
            aes(date,sales,label=sales),
            position = position_dodge(width = 1),
            vjust = 2, size = 5) + 
  geom_text(data=subset(df, year == 2020 & month == "Apr"), 
            aes(date,sales,label=sales),
            position = position_dodge(width = 1),
            vjust = 0, hjust=0,size = 5) +
  geom_text_repel(data=df[5, ], label="Total number of dollars circulation", nudge_y=500, nudge_x=10, color = "blue") +
  labs(title = "Chocolate sales",
       y = "Number of Units", 
       x = "2019                                                   2020")

#plot 2
df2 <- df %>% filter(date == "2020-03-01" | date == "2020-04-04")

choco_date <- as.Date(c("2021-01-01","2021-01-01","2021-01-01",
                        "2022-01-01","2022-01-01","2022-01-01"))
choco_type <- c("Dark", "Milk", "White","Dark", "Milk", "White")
choco_sales <- c(1000,600,100,800,400,200)
df2 <- data.frame(choco_date,choco_type,choco_sales)

dark_start <- df2 %>% filter(choco_type == "Dark" & choco_date == "2021-01-01")
milk_start <- df2 %>% filter(choco_type == "Milk" & choco_date == "2021-01-01")
white_start <- df2 %>% filter(choco_type == "White" & choco_date == "2021-01-01")
dark_end <- df2 %>% filter(choco_type == "Dark" & choco_date == "2022-01-01")
milk_end <- df2 %>% filter(choco_type == "Milk" & choco_date == "2022-01-01")
white_end <- df2 %>% filter(choco_type == "White" & choco_date == "2022-01-01")

p2 <- df2 %>% ggplot(aes(x=choco_date, y=choco_sales, color = choco_type)) + 
  geom_line() +
  geom_point(dark_start, mapping=aes(x=choco_date,y=choco_sales), colour="red", size=2) +
  geom_point(milk_start, mapping=aes(x=choco_date,y=choco_sales), colour="green", size=2) +
  geom_point(white_start, mapping=aes(x=choco_date,y=choco_sales), colour="blue", size=2) +
  geom_point(dark_end, mapping=aes(x=choco_date,y=choco_sales), colour="red", size=2) +
  geom_point(milk_end, mapping=aes(x=choco_date,y=choco_sales), colour="green", size=2) +
  geom_point(white_end, mapping=aes(x=choco_date,y=choco_sales), colour="blue", size=2) +
  geom_text(data=df2[1, ], label = "1000", nudge_x = -30, size = 3) +
  geom_text(data=df2[2, ], label = "600", nudge_x = -25, size = 3) +
  geom_text(data=df2[3, ], label = "100", nudge_x = -25, size = 3)+
  geom_text(data=df2[4, ], label = "800 Dark", nudge_x = 105, size = 3) +
  geom_text(data=df2[5, ], label = "400 Milk", nudge_x = 100, size = 3) +
  geom_text(data=df2[6, ], label = "200 White", nudge_x = 110, size = 3) +
  geom_text(data=df2[1, ], label = "- 20%", nudge_x = 200, nudge_y = -40, size = 3) +
  geom_text(data=df2[2, ], label = "- 33%", nudge_x = 200, nudge_y = -40, size = 3) +
  geom_text(data=df2[3, ], label = "100%", nudge_x = 200, nudge_y = 100, size = 3)+
  scale_x_date(breaks = as.Date(c("2021-01-01", "2022-01-01")),
               labels = c("Last Month \n Mar-20", "This Month \n Apr-20")) +
  labs(title = "Number of chocolate bars sold",
       subtitle = "# OF UNITS           % CHANGE") +
  theme_bw() +
  theme(strip.placement = "outside",
        strip.background = element_rect(fill=NA,colour="grey50"),
        panel.spacing=unit(0,"cm"), 
        axis.line.y = element_blank(),
        axis.line.x = element_line(),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank(),
        panel.grid.major = element_blank(),
        panel.grid.minor = element_blank(),
        panel.border = element_blank(),
        panel.background = element_blank(),
        aspect.ratio = 1,
        plot.title = element_text(color = "black", size = 14),
        plot.subtitle = element_text(color = "dark gray", size = 8),
        legend.position = "none",
        plot.margin = unit(c(0,0,0,0), "lines")) + #margins: (top,right,bottom,left)
  coord_fixed(ratio = 1, clip = 'off') +
  labs(x="",y="")



#cowplot
img_final <- plot_grid(p1, p2, rel_widths = c(2,1))
img_final


#title
title <- ggdraw() + 
  draw_label(
    "Miles per gallon decline with displacement and horsepower",
    fontface = 'bold',
    x = 0,
    hjust = 0
  ) +
  theme(
    # add margin on the left of the drawing canvas,
    # so title is aligned with left edge of first plot
    plot.margin = margin(0, 0, 0, 7)
  )
plot_grid(
  title, img_final,
  ncol = 1,
  # rel_heights values control vertical title margins
  rel_heights = c(0.1, 1)
)

Solution

  • You could generate each panel of your arrangement in a separate plot and arrange them with patchwork:

    st1 <- paste(rep(paste(paste(rep("green", 8), collapse = " "), "\n"), 5), collapse = "")
    st2 <- paste(rep(paste(paste(rep("soccer ball", 5), collapse = " "), "\n"), 5), collapse = "")
    
    # Title panel
    title_panel <- ggplot() + labs(title = "My title") +
      theme(plot.background = element_rect(fill = "#00A2E8"),
            panel.background = element_blank(),
            plot.title = element_text(size = 20, vjust = -1.5))
    
    # Paragraph panels
    paragraph_panel_1 <- ggplot() + theme_void() +
      labs(title = 'People like **the color** <span style = color:"red">red</span>', 
           subtitle = st1) +
      theme(plot.title = element_markdown(size = 20))
    
    paragraph_panel_2 <- ggplot() + theme_void() +
      labs(title = 'Put **cheese** on <span style = color:"purple">pizza</span>',
           subtitle = st2) +
      theme(plot.title = element_markdown(size = 20))
    
    # Arrange with patchwork
    library(patchwork)
    
    title_panel + paragraph_panel_1 + paragraph_panel_2 + p1 + p2 + 
      plot_layout(design = c(area(t = 1, l = 1, b = 1, r = 4),
                             area(t = 2, l = 1, b = 2, r = 2),
                             area(t = 2, l = 3, b = 2, r = 4),
                             area(t = 3, l = 1, b = 12, r = 2),
                             area(t = 3, l = 3, b = 12, r = 3)))
    

    enter image description here