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 no avail to uses of writeLines("\n"), cat('\r\n\r\n') per this SO.
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: "Stack Overflow Consecutive PNG"
author: "Rick Pack"
date: "11/20/2019"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## Copy a PNG file as multiple files
```{r png_copy, echo=FALSE}
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
```{r png_show, echo=FALSE}
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")
}
```
You can use R Markdown syntax within the for loop instead of the png package. Given you have the images in the same directory as your Rmd, the following should work:
```{r, results = "asis"}
filelist <- c("Rlogo_1", "Rlogo_2", "Rlogo_3")
for(i in filelist) {
cat(paste0("![](", i, ".png)"), "\n")
cat("\n\n\\pagebreak\n")
}
```
Output:
See this related question for more info: Insert images using knitr::include_graphics in a for loop
Related
How can we export multiple markdown files (HTML, PDF, WORD) from R into zip file. Many thanks for your help!
Suppose, we have the following Rmarkdown file (the source file) which can be rendered as pdf, html and word documents.
multiple_output.Rmd
---
title: "multiple outputs"
output:
word_document: default
html_document: default
pdf_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Now to render this source file to pdf, html, and word document at once and then zip it into a folder, we run the following code from another Rscript file (rscript file needs to be in the same place where your Rmd source file is)
file.R
# create a folder where the multiple output files will be placed
dir.create("multiple_output")
# then render the source file to that created folder
rmarkdown::render(
"multiple_outupt.Rmd", output_dir = "multiple_output/",
output_format = "all"
)
# create file paths for zipping
files_for_zip <- dir('multiple_output', full.names = TRUE)
# zip the folder
zip(zipfile = "multiple_output", files = files_for_zip)
Then we will have the zipped folder multiple_output.zip.
As the example, if you create a new R markdown file and save it as 'test'. Can one then run or deploy this test.Rmd file from within a normal R script. The purpose being to generate the output in HTML, without having to open the .Rmd file.
I'm hoping to create one master file to do this for many markdown files in one go; which would save considerable time as you then don't have to open many markdown files and wait for each one to complete.
You are looking for rmarkdown::render().
Contents of "test.Rmd"
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
Contents of script.R
# provided test.Rmd is in the working directory
rmarkdown::render("test.Rmd")
A Way to Render Multiple Rmd
cwd_rmd_files <- list.files(pattern = ".Rmd$")
lapply(cwd_rmd_files, rmarkdown::render)
Thanks the-mad-statter, your answer was very helpful. The issue I faced, required me to prepare markdown dynamically. By adapting your code, that's easily possible:
Contents of "test_dyn.rmd"
---
title: "Untitled"
output: html_document
---
The chunk below adds formatted text, based on your inputs.
```{r text, echo=FALSE, results="asis"}
cat(text)
```
The chunk below uses your input in as code.
```{r results}
y
```
Contents of "script_dyn.r"
in_text <- c("**Test 1**", "*Test 2*")
in_y <- 1:2
lapply(1:2, function(x) {
text <- in_text[[x]]
y <- in_y[[x]]
rmarkdown::render(input = "test_dyn.rmd", output_file = paste0("test", x))
})
Like this you can create files with different text and different variables values in your code.
I'm searching for a way to reuse r-code in latex using knitr. I have multiple excel documents, that I want to import, analyze and plot in the same way throughout my thesis. Right now I am making a new .rnw file for each excel document that I have. This means, that if I want to change anything, I have to do it in every .rnw file - which seems like the wrong approach. Is there a way, where I can call one .rnw file from the parent .rnw and providing it with an excel filename to import and work with.
Yes there is. You can use both the params and render function to help with this. If you are unfamiliar with parameters look here params and here for render. I wrote iris and mtcars to excel for the examples below. In the markdown below I call the excel parameter in the chunk which is the excel file and just print the first 10 rows.
---
title: "iris"
output: pdf_document
params:
excel: "G:/iris2.xlsx"
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r cars}
head(xlsx::read.xlsx(params$excel,sheetIndex = 1))
```
Now to change the excel file you can use lapply and the render function in a .R file.
#create list of excel files
exldocs <- c("G:/mtcars2.xlsx", "G:/iris2.xlsx")
#call the renders.rmd (above), pass the list of excel files to overwrite the #default param field, output a new pdf (call it whatever you want)
lapply(exldocs, function(x){
rmarkdown::render("G:/renders.Rmd", params = list(excel = x),
output_file =paste0(substr(x,1,nchar(x)-4),"pdf")
)})
You can use knitr::knit and use the envir argument as follows. Here is the .Rnw file
% parameterized_reports.Rnw
\documentclass{article}
\begin{document}
<<>>=
foo
#
\end{document}
Here is the R code
tmp <- environment()
tmp$foo <- "xyz"
knitr::knit("parameterized_reports.Rnw", envir = tmp, output = "output.tex")
tools::texi2pdf("output.tex")
system('open output.pdf')
The result is
In RStudio, whenever I make a new Markdown it always has default code. How do I remove it?
Here's the code that shows up.
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r cars}
summary(cars)
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Note that the `echo = FALSE` parameter was added to the code chunk to prevent printing of the R code that generated the plot.
Every time, when creating a Rmd file, Rstudio will open a Rmd template:
https://github.com/rstudio/rstudio/blob/822e558c7a274de464f992f69e3acee2fde5ab04/src/cpp/session/modules/SessionRMarkdown.R
# given a path to a folder on disk, return information about the R Markdown
# template in that folder.
.rs.addFunction("getTemplateDetails", function(path) {
# check for required files
templateYaml <- file.path(path, "template.yaml")
skeletonPath <- file.path(path, "skeleton")
if (!file.exists(templateYaml))
return(NULL)
if (!file.exists(file.path(skeletonPath, "skeleton.Rmd")))
return(NULL)
# load template details from YAML
templateDetails <- yaml::yaml.load_file(templateYaml)
# enforce create_dir if there are multiple files in /skeleton/
if (length(list.files(skeletonPath)) > 1)
templateDetails$create_dir <- TRUE
templateDetails
})
Hence the simplest solution would be:
go to xxx\RStudio\resources\templates folder, where your
Rstudio installed
open r_markdown_v2.Rmd file, and delete
everthing
save it
Now, everytime, when you open a rmarkdown, you can have just the yaml part.
Is there an expedient way to extract and load into R a List of Figures that knitr and latex have created in a PDF document?
My PDF has scores of figures; they are sorely in need of being tracked and organized, which the List of Figures helps do. But having the List in R would help in many ways.
Snipping the List from the PDF, pasting it into Excel, and working with that worksheet is one arduous route, but it would be quicker and smoother if it were possible to locate the List of Figures and load it directly (more or less) into R. The knitting process creates many files and perhaps the List lurks within one of them?
Here is a small example simply to create a List of Figures, borrowed from a question on hiding captions here
\documentclass{article}
\usepackage{graphicx}
\setcounter{topnumber}{3}% Just for this example
\begin{document}
\listoffigures
\begin{figure}
\addcontentsline{lof}{figure}{Example image A}%
\centering
\includegraphics[height=4\baselineskip]{example-image-a}
Example image A
\end{figure}
\begin{figure}
\addcontentsline{lof}{figure}{\protect\numberline{}Example image B}%
\centering
\includegraphics[height=4\baselineskip]{example-image-b}
Example image B
\end{figure}
\begin{figure}
\centering
\includegraphics[height=4\baselineskip]{example-image-c}
\caption{Example image C}
\end{figure}
\end{document}
You can do something like this:
---
title: "Untitled"
output:
pdf_document:
fig_caption: true
---
```{r setup, include=FALSE}
gen_lof <- TRUE
if (gen_lof) {
unlink("/tmp/figures.csv")
cat("pdf_name,output_path,caption,subcaption\n",
file="/tmp/figures.csv", append=TRUE)
knitr::knit_hooks$set(plot=function(x, opt) {
cat(x, ",",
opt$fig.path, ",",
opt$fig.cap, ",",
opt$fig.scap, "\n",
sep="", file="/tmp/figures.csv", append=TRUE)
})
}
```
I slightly modified the default RStudio example knitr doc to add two figures with names and captions.
Set gen_lof to FALSE for your normal PDF creation (using a hook mean having to knit once for the full output PDF and once again for just the CSV of figures). Set it to TRUE and knit it to get an list of figures output (wherever you want, I just used that filename for convenience) file that will look like:
pdf_name,output_path,caption,subcaption
Untitled_files/figure-latex/cars-1.pdf,Untitled_files/figure-latex/,lines cars,
Untitled_files/figure-latex/pressure-1.pdf,Untitled_files/figure-latex/,points cars,
While they may have pdf for an output type, it should not be too much trouble to do a 1:1 comparison.
You also have access to all the knitr chunk options this way. i.e.:
aniopts autodep background cache cache.lazy cache.path
cache.rebuild cache.vars child code collapse comment
crop dependson dev dev.args dpi echo engine error eval
external
fig.align fig.cap fig.cur fig.env fig.ext fig.height
fig.keep fig.lp fig.num fig.path fig.pos fig.retina
fig.scap fig.show fig.subcap fig.width
highlight include interval label message out.extra
out.height out.height.px out.width out.width.px
params.src prompt purl ref.label render results
sanitize size split strip.white tidy tidy.opts warning
(I separated out the "fig" specific options on purpose).
The use of a variable to trigger generation means you can code up parameterized knitr workflows to do one gen to get figures and then another to get the final PDF.
Others may have more optimal ways.
As page numbers are not required, it is enough to save fig.cap from each chunk.
This can be done using a chunk hook that saves options$fig.cap in a global variable and saves this variable to a file at the end of the knitting process.
\documentclass{article}
\begin{document}
<<setup>>=
library(knitr)
figureCaptions <- c()
knit_hooks$set(listit = function(before, options, envir) {
if (!before) figureCaptions <<- c(figureCaptions, options$fig.cap)
})
<<fig.cap = "First one", listit = TRUE>>=
plot(1)
#
<<fig.cap = "Second one", listit = TRUE>>=
plot(rnorm(10))
#
<<final>>=
save(figureCaptions, file = "figureCaptions.RData")
#
\end{document}
It should be better to save the caption only after the chunk has been evaluated (if (!before)) in order to avoid problems with eval.after.
To access the captions afterwards, use load("figureCaptions.RData").