Search code examples
rggplot2patchwork

How to set dimension for long multi-plot figure in patchwork?


I am learning R and I would like to produce a long yet readable image of 11 plots (one column) using the patchwork package in R. However, because this are so many plots, the output image gets distorted/ squished and is unreadable. Here is my reprex:

data(diamonds)
library(ggplot2)
library(patchwork)

a <- ggplot(data = diamonds, aes(y = clarity)) +
  geom_bar(stat = "count", orientation = "y")
b <- ggplot(data = diamonds, aes(y = color)) +
  geom_bar(stat = "count", orientation = "y")
c <- ggplot(data = diamonds, aes(y = table)) +
  geom_bar(stat = "count", orientation = "y")
d <- ggplot(data = diamonds, aes(y = cut)) +
  geom_bar(stat = "count", orientation = "y")
e <- ggplot(data = diamonds, aes(y = x)) +
  geom_bar(stat = "count", orientation = "y")
f <- ggplot(data = diamonds, aes(y = depth)) +
  geom_bar(stat = "count", orientation = "y")
g <- ggplot(data = diamonds, aes(y = carat)) +
  geom_bar(stat = "count", orientation = "y")
h <- ggplot(data = diamonds, aes(y = z)) +
  geom_bar(stat = "count", orientation = "y")

a + b + c + d + e + f + g + h +
  plot_layout(ncol = 1)
         
      

This is the image produced: enter image description here

How can I lock the aspect so that it is readable and even scrollable in MS Word, if this is possible?

Please let me know if I can provide more information or need to use a different package. Ultimately I will export this figure as a .png to Microsoft Word. Thank you.


Solution

  • I think that you are running into two problems:

    1. The plot size of the device
    2. The aspect ratio of the plots themselves

    The first will be determined by the size of the device R plots to. The plots will attempt to fill the entire device. If you set the device so that it has more vertical than horizontal space, the plots will self-adjust. The problem is that you are trying to include a lot of plots on a single device. For a single piece of paper, it will be difficult to read all of them.

    The other issue tells ggplot how you want each graph displayed. In this case, the aspect ratio between x- and y- will be set regardless of the area included in the device.

    Below, I solve the first problem by breaking the columns of diamonds into two sets of five. I then save a PNG image for each, setting the size of the PNG to letter paper with 1-inch margins. I solve the second problem by setting theme(aspect.ratio = 1) to ensure a series of square plots (you can play with this to create different aspect ratios).

    I wrap the whole thing in a function using the "don't repeat yourself" (DRY) principle of programming.

    library(ggplot2)
    library(patchwork)
    
    bplt <- function(yvar) {
        ggplot(diamonds, aes_(y = as.name(yvar))) + geom_bar() +
            theme(aspect.ratio = 1)
    }
    wrap_plots(lapply(names(diamonds)[1:5], bplt), ncol = 1)
    ggsave("~/tmp/diamond_features1.png", width = 6.5, height = 9, units = "in")
    wrap_plots(lapply(names(diamonds)[6:10], bplt), ncol = 1)
    ggsave("~/tmp/diamond_features2.png", width = 6.5, height = 9, units = "in")