Show PNG images consecutively with loop in R Markdown chunk (HTML)

Can one use an R Markdown chunk loop to show multiple graphics files (e.g., PNG) consecutively (one above the other) in HTML output? This loop would identify the files in a vector, such as via list.files().

I have experimented with uses of writeLines("\n"), cat('\r\n\r\n'), knit_expand() [per this SO to no avail].

This R Markdown code (formatted below but link is .Rmd) is a reproducible example with an attempt using writeLines("\n") and cat('\r\n\r\n'). Please note this copies 5 R logo PNG (only 12kb) file copies into your working directory.


title: "Consecutive PNG Loop Attempt"
author: "Rick Pack"
date: "11/20/2019"
output: html_document

knitr::opts_chunk$set(echo = TRUE)

Copy a PNG file as multiple files

for (q in 1:5) {
 file.copy(list.files(system.file("img", package = "png"), 
                      full.names = TRUE),
           getwd())
 file.rename("Rlogo.png", paste0("Rlogo_",q,".png"))
}

Only one R logo shown instead of the five available

library(png)
# Providing the folder so you can delete the png files
# created above
print(getwd())
 all_img <- list.files(full.names = TRUE)[grepl(
     "Rlogo", list.files())]
 for (j in 1:length(all_img)) {  
 grid::grid.raster(readPNG(all_img[j]))
writeLines("\n")
cat('\r\n\r\n')  
cat("\n\n\\pagebreak\n")
 }

Showing only one PNG file appeared

Hi @rick_pack2,

I have a couple approaches in mind. Can you confirm what you are hoping to achieve? You want to just loop over a vector of image files and make sure they all show up in the rendered document?

Yes and thank you, @mattwarkentin, I want to loop over a vector of image files and show all of them in the rendered document.

What about something like this:

---
output: html_document
---

```{r}
read_and_plot <- function(path) {
  x <- png::readPNG(path)
  plot(x)
}
```

```{r out.width="50%"}
# replace path with path to your image files
purrr::walk(fs::dir_ls('path/to/pngs/here', 
                       type = 'file', glob = '*.png'), 
            read_and_plot)
```

Thank you, Matt, but that did not work. The plot function prints unexpected output and when I printed the readPNG() output, I still have the problem of each image file replacing the prior one.

Rather than using a loop, this Stack Overflow response caused me to discover can point include_graphics() to a vector containing the full path to graphics files a la:
knitr::include_graphics(all_img)

2 Likes

Great, glad you got it all working. The walk() code worked on my end, not sure why it didn't for you. But knitr::include_graphics() is a simpler solution.