5

I am creating a series of plots using ggplot2. Each of these are programmatically named and I want use the names to give each their own figure caption. I want to pull the names from the list and pass them to fig.cap dynamically.

Is there a way to do this? Here is a MCVE, and you can switch between the list and the individual plots to see the figures disappear or show up:

---
output: pdf_document
---

```{r, include = FALSE}
library(ggplot2)
library(knitr)
opts_chunk$set(echo=FALSE)
```

```{r}
## Plot 1
listOfPlots <- list(
  # Plot 1
  ggplot(data = diamonds) +
    geom_point(aes(carat, price)),

  ## Plot 2
  ggplot(data = diamonds) +
    geom_point(aes(carat, depth))
)

names(listOfPlots) <- c("This is caption 1", "This is caption 2")
```


```{r, fig.cap = c("This is caption 1", "This is caption 2"), echo=TRUE}

listOfPlots

# listOfPlots$`This is caption 1`
# listOfPlots$`This is caption 2`
```

Notes:

  • Yihui and others have said (https://groups.google.com/forum/#!topic/knitr/MJVLiVyGCro), that to have multiple figures in a chunk and give them a figure caption, you need to have echo=TRUE because inline figures and pandoc stuff.
  • I don't want to show code and the number of figures may be variable so I don't want to hard code things. Interestingly, using a list of ggplots also does not work even if echo=TRUE. I have to individually call each ggplot.
Michael Harper
  • 14,721
  • 2
  • 60
  • 84
Sahir Moosvi
  • 549
  • 2
  • 21
  • 1
    As a R Markdown tip, you can use the `include=FALSE` argument in the first code chunk to suppress any outputs. This means you don't have to wrap all the functions in `SupressStartupMessages()`: https://yihui.name/knitr/options/#code-evaluation . Hope that helps :) – Michael Harper Oct 14 '18 at 08:54

1 Answers1

5

There needs to be spaces between plots in R Markdown if they are to be given their own caption. As stated by Yihui on your link, the trick here is to add some line breaks between the two images.

```{r, fig.cap=c("Caption 1", "Caption 2")} 
listOfPlots[[1]]
cat('\n\n') 
listOfPlots[[2]]
``` 

Note, the double square brackets are used to only return the plot itself.

Using a Loop

Assuming you are looking for a more generalizable method which could work for a list of any length, we can automate the creation of the line breaks between the plots using a loop. Note that results="asis" is required in the chunk header:

```{r, fig.cap=c("Caption 1", "Caption 2"), echo=FALSE, results="asis"} 

for(plots in listOfPlots){
  print(plots)
  cat('\n\n') 
}

``` 

enter image description here

As a final tip, you may wish to use the name of the list directly within the caption. The syntax {r, fig.cap = names(listOfPlots)} would be able to achieve this.

Michael Harper
  • 14,721
  • 2
  • 60
  • 84
  • You can also use the `glue::glue_data()` package as well to create a figure caption as well. For example, `fig.cap = glue::glue_data(diamonds, "Figure Caption for {var}")`. This is useful if you create plots from stratified data using `tidyr::nest()` and `purrr::map()`. – phargart Aug 30 '22 at 14:37