R knitr Markdown: Output Plots within For Loop

Viewed 35420

I would like to create an automated knitr report that will produce histograms for each numeric field within my dataframe. My goal is to do this without having to specify the actual fields (this dataset contains over 70 and I would also like to reuse the script).

I've tried a few different approaches:

  • saving the plot to an object, p, and then calling p after the loop
    • This only plots the final plot
  • Creating an array of plots, PLOTS <- NULL, and appending the plots within the loop PLOTS <- append(PLOTS, p)
    • Accessing these plots out of the loop did not work at all
  • Even tried saving each to a .png file but would rather not have to deal with the overhead of saving and then re-accessing each file

I'm afraid the intricacies of the plot devices are escaping me.

Question

How can I make the following chunk output each plot within the loop to the report? Currently, the best I can achieve is output of the final plot produced by saving it to an object and calling that object outside of the loop.

R markdown chunk using knitr in RStudio:

```{r plotNumeric, echo=TRUE, fig.height=3}
suppressPackageStartupMessages(library(ggplot2))
FIELDS <- names(df)[sapply(df, class)=="numeric"]
for (field in  FIELDS){
  qplot(df[,field], main=field)  
}
```

From this point, I hope to customize the plots further.

5 Answers

Wish to add a quick note: Somehow I googled the same question and get into this page. Now in 2018, just use print() in the loop.

for (i in 1:n){
...
    f <- ggplot(.......)
    print(f)
}

For knitting Rmd to HTML, I find it more convenient to have a list of figures. In this case I get the desirable output with results='hide' as follows:

---
title: "Make a list of figures and show it"
output: 
  html_document
---


```{r}
suppressPackageStartupMessages({
  library(ggplot2)
  library(dplyr)
  requireNamespace("scater")
  requireNamespace("SingleCellExperiment")
})
```


```{r}
plots <- function() {
  print("print")
  cat("cat")
  message("message")
  warning("warning")
  
  # These calls generate unwanted text
  scater::mockSCE(ngene = 77, ncells = 33) %>%
    scater::logNormCounts() %>%
    scater::runPCA() %>%
    SingleCellExperiment::reducedDim("PCA") %>%
    as.data.frame() %>%
    {
      list(
        f12 = ggplot(., aes(x = PC1, y = PC2)) + geom_point(),
        f22 = ggplot(., aes(x = PC2, y = PC3)) + geom_point()
      )
    }
}
```

```{r, message=FALSE, warning=TRUE, results='hide'}
plots()
```

Only the plots are shown and the warnings (which you can switch off, as well).

Related