1

Consider this simple example

library(dplyr)
library(ggplot)
library(patchwork)

mytib <- tibble(group = as.factor(c(1,1,1,1,2,2,2,2,3,3,3,3)),
       y = c(1,2,3,42,50,400,3,3,2,3,3,4),
       x = c('a','b','c','d','a','b','c','d','a','b','c','d'))


p1 <- mytib %>% ggplot(aes(x = x, y = y, fill = group)) +
  geom_col() + ggtitle('this is a messy chart')+
  coord_flip()+
  xlab('Hello') +
  ylab('This is a nice comment')

Now I use patchwork to combine the charts so that I obtain 3 rows of 3 charts each on a regular a4 pdf page

(p1 + p1 + p1)/
(p1 + p1 + p1)/
(p1 + p1 + p1)

ggsave(file="a4_output.pdf", width = 210, height = 297, units = "mm")

enter image description here

The output is a nice a4 pdf but the problem is that the charts on the pdf are very stretched. Is there a way to preserve their original ratio (on the pdf) so that they look less stretched, even three on a single row? I dont mind if they look smaller.

Any ideas? Thanks!

ℕʘʘḆḽḘ
  • 18,566
  • 34
  • 128
  • 235
  • 4
    Is there something keeping you from using `ggplot2::facet_*`? It would save space used on redundant legends, redundant axes, multiple titles (which can be accomplished via facet labels, though different look). – r2evans Feb 24 '20 at 01:52
  • thanks for your help. The issue is that the charts come from different datasets, so I cannot easily use facet_grid. There has to be another way (I hope :) ) – ℕʘʘḆḽḘ Feb 24 '20 at 01:55
  • 1
    Add an empty row at the bottom. Do e.g. 5 rows with the last ones being just `ggplot()`. – Axeman Feb 24 '20 at 02:03
  • Is it just "different datasets", or are the completely different looking data? If the structure is similiar-enough, you can `bind_rows` the columns you need, adding a column to indicate the origin dataset, which can be used as the facet label. – r2evans Feb 24 '20 at 02:04
  • 1
    completely different charts. @Axeman that looks like a crazy trick :) – ℕʘʘḆḽḘ Feb 24 '20 at 02:07
  • 2
    If you shift the legends to the bottom `theme(legend.position="bottom")`, it'll have a strong effect on the aspect ratio. – r2evans Feb 24 '20 at 02:08
  • I know but assume you have to keep the charts as is. I guess the only way to achieve the expected result is to make the charts smaller... – ℕʘʘḆḽḘ Feb 24 '20 at 02:10
  • Rotate to landscape? – r2evans Feb 24 '20 at 02:13
  • I have to keep it a4 portrait. that is the constraint. I mean this must be pretty common. You write a report and you want to show 6 cute little charts on a single page... – ℕʘʘḆḽḘ Feb 24 '20 at 02:14
  • 1
    As Axeman suggested, add one or more empty rows. Or just constrain the figure height so that it is not as tall as an a4 page. Sorry, I don't have much more to add. – r2evans Feb 24 '20 at 02:25
  • I guess the empty plot solution is the easiest. Have a look also at https://patchwork.data-imaginist.com/articles/guides/layout.html You can pretty exactly control the layout specifying it with something like `layout = '#ABCD' etc` it must be a rectangle but it sets the relative dimensions of each plot, and the hash key is an empty space – tjebo Feb 24 '20 at 08:39
  • but the empty plot does not work for me. can you make it work with the layout in patchwork then? – ℕʘʘḆḽḘ Feb 24 '20 at 11:33
  • 1
    @Axeman your previous answer helped find one solution :) Thanks – tjebo Feb 24 '20 at 23:48
  • 1
    Hey I have added another solution, hope this helps – tjebo Mar 02 '20 at 21:25

1 Answers1

2

The problem is the changing plot ratio. Now, coord_flip doesn't work with fixed ratio - but user Axeman explained how to deal with this problem - use ggstance!! I changed the plot mildly, using geom_colh, switched your x and y, and added a fixed ratio. Now we can use your plot layout, or simply pack the plots in a list and use wrap_plots. I did not use the reprex output because I am sharing the screenshot from the pdf output.

library(tidyverse)
library(patchwork)
library(ggstance)

mytib <- tibble(group = as.factor(c(1,1,1,1,2,2,2,2,3,3,3,3)),
                y = c(1,2,3,42,50,400,3,3,2,3,3,4),
                x = c('a','b','c','d','a','b','c','d','a','b','c','d'))

p1 <- 
  mytib %>% ggplot(aes(x = y, y = x, fill = group)) +
  geom_colh() + ggtitle('this is a messy chart')+
  coord_fixed(100)+
  xlab('Hello') +
  ylab('This is a nice comment')

plotlist <- list()
for(i in 1:9) { plotlist[[i]] <- p1 }

ggsave(plot = wrap_plots(plotlist), file="a4_output.pdf", width = 210, height = 297, units = "mm")

enter image description here

Another solution is to add another row - not with an empty plot, but using plot_layout

(p1 + p1 + p1)/
  (p1 + p1 + p1)/
  (p1 + p1 + p1) +
  plot_layout(nrow = 4)
tjebo
  • 21,977
  • 7
  • 58
  • 94