2

I am writing a report in R markdown with a pdf output. I have several plots and I would like to display four plots per page laid out in a 2x2 matrix. Is there a way to get them to display like that with separate captions?

Here is what I have tried so far:

  • Package gridExtra - I can easily setup the layout I want but I wasn't able to add captions to the plots.Is there an option to add captions to the plot in grid.arrange?

  • Placing each plot in a different chunk and playing with R chunk options. Basically setting out.width='.49\\linewidth', fig.align='right' and fig.align='left' alternatively. Here I can set individual captions with fig.cap but the plots always show up on separate pages.

  • I tried playing with the fig.width and fig.height options and was able to get them to display on the same page on their respective left or right sides of the page. However the caption always takes the full page width and stays in center instead of wrapping with the plot size. Is there a way to make caption follow the plot sizing rules?

Here is a sample code:

```{r, echo=FALSE, cache=FALSE, results=FALSE, warning=FALSE,  comment=FALSE, message= FALSE, eval =T, fig.height= 9}

p1<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
labs(caption = "Lorem ipsum dolor sit amet, consectetur adipiscing     elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ")+
theme(plot.caption = element_text(hjust = 0.5))

p2<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
labs(caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.  ")+
theme(plot.caption = element_text(hjust = 0.5))

p3<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
labs(caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ")+
theme(plot.caption = element_text(hjust = 0.5))

p4<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
labs(caption = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. ")+
theme(plot.caption = element_text(hjust = 0.5))

library(gridExtra)
grid.arrange(p1,p2,p3,p4)
```

Here is the output image I'd appreciate any help. Thanks!

  • 1
    at the end of each ggplot you can add captions like this then use gridExtra - `labs(caption = "Hi world")` – Mike Apr 18 '18 at 19:29
  • Thanks I tried that just now. It works except all the captions are on top of each other. Is there a way to neatly wrap the captions under the plot? – shashwat vajpeyi Apr 18 '18 at 19:43
  • Can you share your code/data so I can see the issue? – Mike Apr 18 '18 at 20:12
  • If you are just trying to wrap the text in the caption you can do this `labs(caption = "Hi \nworld")` . the \n will put world on the second line – Mike Apr 18 '18 at 20:37
  • If you only want PDF output you can check out the use of sibfigure https://stackoverflow.com/a/49086985/7347699 – Michael Harper Apr 18 '18 at 21:33
  • @Mike I added a sample code and I tried adding \n but I have twenty plots and its just taking forever to edit each caption individually. I am surprised that its not more straight forward – shashwat vajpeyi Apr 19 '18 at 00:23

1 Answers1

9

You can use subfigures within LaTeX Outputs, as describe here. If you have lots of plots and you want to provide the captions easier, you can specify these in a list (i.e. captions <- c("Caption 1", "Caption 2") before the chunk and the provide this list to the chunk as fig.subcap=captions

---
output: pdf_document
header-includes:
  - \usepackage{subfig}
---  

```{r}
captions <- c("Caption 1",
              "Caption 2", 
              "Caption 3",
              "Caption 4: a very very very very very very very very very long one")
```


```{r, echo=FALSE, cache=FALSE, results=FALSE, warning=FALSE,  comment=FALSE, message= FALSE, eval =T,  fig.cap = "Overall Caption", fig.subcap=captions, out.width='.49\\linewidth', fig.asp=1, fig.ncol = 2}
library(ggplot2)
p1<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
theme(plot.caption = element_text(hjust = 0.5))

p2<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
theme(plot.caption = element_text(hjust = 0.5))

p3<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
theme(plot.caption = element_text(hjust = 0.5))

p4<- ggplot(mpg, aes(displ, hwy, colour = class)) + 
geom_point()+
theme(plot.caption = element_text(hjust = 0.5))

p1
p2
p3
p4
```

enter image description here

Edit

To ensure there is margin between the subfigures, you can add the margins option when loading the package:

  - \usepackage[margin = 8pt]{subfig}

Check out the other options in the package documentation: http://anorien.csc.warwick.ac.uk/mirrors/CTAN/macros/latex/contrib/subfig/subfig.pdf

Michael Harper
  • 14,721
  • 2
  • 60
  • 84