Search code examples
rdataframeggplot2plotfacet-wrap

How to fill blank section of faceted ggplot in R?


Data

Here is my data:

work <- structure(list(Mins_Work = c(435L, 350L, 145L, 135L, 15L, 60L, 
60L, 390L, 395L, 395L, 315L, 80L, 580L, 175L, 545L, 230L, 435L, 
370L, 255L, 515L, 330L, 65L, 115L, 550L, 420L, 45L, 266L, 196L, 
198L, 220L, 17L, 382L, 0L, 180L, 343L, 207L, 263L, 332L, 0L, 
0L, 259L, 417L, 282L, 685L, 517L, 111L, 64L, 466L, 499L, 460L
), Mins_Sleep = c(300L, 540L, 540L, 480L, 480L, 480L, 480L, 420L, 
300L, 240L, 480L, 300L, 420L, 360L, 390L, 405L, 420L, 360L, 420L, 
350L, 420L, 450L, 445L, 480L, 300L, 400L, 310L, 390L, 350L, 450L, 
390L, 390L, 510L, 452L, 310L, 360L, 500L, 360L, NA, NA, 420L, 
420L, 420L, 382L, 430L, 393L, 240L, 400L, 480L, 450L), Coffee_Cups = c(3L, 
0L, 2L, 6L, 4L, 5L, 3L, 3L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 2L, 0L, 
1L, 1L, 4L, 4L, 3L, 0L, 1L, 3L, 0L, 0L, 0L, 0L, 2L, 0L, 1L, 2L, 
3L, 2L, 2L, 4L, 3L, 6L, 6L, 3L, 4L, 6L, 8L, 3L, 5L, 0L, 2L, 2L, 
8L), Tea_Cups = c(2L, 4L, 2L, 0L, 0L, 2L, 0L, 2L, 4L, 0L, 0L, 
0L, 2L, 6L, 5L, 0L, 2L, 0L, 2L, 4L, 0L, 0L, 0L, 2L, 1L, 0L, 4L, 
4L, 4L, 2L, 1L, 0L, 2L, 0L, 0L, 4L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 2L, 0L, 1L, 0L, 2L, 0L), Time_Wake = c(500L, 715L, 600L, 
600L, 700L, 600L, 700L, 500L, 500L, 500L, 500L, 700L, 645L, 700L, 
630L, 645L, 700L, 600L, 700L, 550L, 700L, 730L, 725L, 800L, 600L, 
640L, 600L, 730L, 650L, 830L, 630L, 630L, 830L, 722L, 641L, 800L, 
720L, 700L, NA, NA, NA, 700L, 700L, 622L, 710L, 632L, 400L, 640L, 
700L, 730L)), class = "data.frame", row.names = c(NA, -50L))

Oftentimes I have odd combinations of variables that don't neatly fit into a faceted grid in ggplot. As an example, here is a code to stack my numeric data into one plot:

work %>% 
  keep(is.numeric) %>% 
  gather() %>% 
  ggplot(aes(x=value))+
  geom_density()+
  facet_wrap(~key,
             scales = "free")

However, as you can see, there are five plots, and arranging the rows and columns doesn't really fix the issue because it is an odd number:

PLOTS

I'm wonder if there is a possible way to paste in some kind of text box in this sixth quadrant of the faceted plot. I'm thinking something like this:

enter image description here

How can one accomplish this goal?


Solution

  • One option is to access the 'blank space' using gtable/grid, e.g.

    library(tidyverse)
    library(gtable)
    library(grid)
    
    work <- structure(list(Mins_Work = c(435L, 350L, 145L, 135L, 15L, 60L, 
                                         60L, 390L, 395L, 395L, 315L, 80L, 580L, 175L, 545L, 230L, 435L, 
                                         370L, 255L, 515L, 330L, 65L, 115L, 550L, 420L, 45L, 266L, 196L, 
                                         198L, 220L, 17L, 382L, 0L, 180L, 343L, 207L, 263L, 332L, 0L, 
                                         0L, 259L, 417L, 282L, 685L, 517L, 111L, 64L, 466L, 499L, 460L
    ), Mins_Sleep = c(300L, 540L, 540L, 480L, 480L, 480L, 480L, 420L, 
                      300L, 240L, 480L, 300L, 420L, 360L, 390L, 405L, 420L, 360L, 420L, 
                      350L, 420L, 450L, 445L, 480L, 300L, 400L, 310L, 390L, 350L, 450L, 
                      390L, 390L, 510L, 452L, 310L, 360L, 500L, 360L, NA, NA, 420L, 
                      420L, 420L, 382L, 430L, 393L, 240L, 400L, 480L, 450L), Coffee_Cups = c(3L, 
                                                                                             0L, 2L, 6L, 4L, 5L, 3L, 3L, 2L, 2L, 3L, 1L, 1L, 3L, 2L, 2L, 0L, 
                                                                                             1L, 1L, 4L, 4L, 3L, 0L, 1L, 3L, 0L, 0L, 0L, 0L, 2L, 0L, 1L, 2L, 
                                                                                             3L, 2L, 2L, 4L, 3L, 6L, 6L, 3L, 4L, 6L, 8L, 3L, 5L, 0L, 2L, 2L, 
                                                                                             8L), Tea_Cups = c(2L, 4L, 2L, 0L, 0L, 2L, 0L, 2L, 4L, 0L, 0L, 
                                                                                                               0L, 2L, 6L, 5L, 0L, 2L, 0L, 2L, 4L, 0L, 0L, 0L, 2L, 1L, 0L, 4L, 
                                                                                                               4L, 4L, 2L, 1L, 0L, 2L, 0L, 0L, 4L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 
                                                                                                               0L, 2L, 0L, 1L, 0L, 2L, 0L), Time_Wake = c(500L, 715L, 600L, 
                                                                                                                                                          600L, 700L, 600L, 700L, 500L, 500L, 500L, 500L, 700L, 645L, 700L, 
                                                                                                                                                          630L, 645L, 700L, 600L, 700L, 550L, 700L, 730L, 725L, 800L, 600L, 
                                                                                                                                                          640L, 600L, 730L, 650L, 830L, 630L, 630L, 830L, 722L, 641L, 800L, 
                                                                                                                                                          720L, 700L, NA, NA, NA, 700L, 700L, 622L, 710L, 632L, 400L, 640L, 
                                                                                                                                                          700L, 730L)), class = "data.frame", row.names = c(NA, -50L))
    p <- work %>% 
      keep(is.numeric) %>% 
      gather() %>% 
      ggplot(aes(x=value))+
      geom_density()+
      facet_wrap(~key,
                 scales = "free")
    
    note <- paste("Notes on Plots:\n",
          "- coffee skew\n",
          "- sleep semi-normal\n",
          "- work is weird\n",
          "- etc\n",
          "- etc")
    
    p2 <- ggplot() +
      annotate("text",
               x = 0,
               y = 0,
               label = note,
               size = 5,
               hjust = 0) +
      theme_void()
    
    pg <- ggplotGrob(p)
    #> Warning: Removed 5 rows containing non-finite values (stat_density).
    p2g <- ggplotGrob(p2)
    pl <- gtable_filter(pg, 'panel', trim=F)$layout
    pg <- gtable_add_grob(pg, p2g, t=max(pl$t), l=max(pl$l), r = pl$r[3])
    
    grid.newpage()
    grid.draw(pg)
    

    Created on 2022-09-15 by the reprex package (v2.0.1)