RMarkdown Beamer make slide titles and add figures in loop - r

I am new to RMarkdown and Beamer. I am trying to make a set of slides where each slide contains a JPG. I have a dozen to loop through. How do I set this up in a loop?
Here is the RMD file:
---
title: 'slideshow'
output:
beamer_presentation:
theme: "AnnArbor"
---
# Introduction
## Blah
- Text
- Here
- Etc.
# Images
## pic_1
```{r echo=FALSE, out.width = '100%'}
knitr::include_graphics("../images/modelA_pic_1.jpg")
```
## pic_2
```{r echo=FALSE, out.width = '100%'}
knitr::include_graphics("../images/modelA_pic_2.jpg")
```
## pic_3
```{r echo=FALSE, out.width = '100%'}
knitr::include_graphics("../images/modelA_pic_3.jpg")
```
## pic_4
```{r echo=FALSE, out.width = '100%'}
knitr::include_graphics("../images/modelA_pic_4.jpg")
```
I know I can put the slide titles and figure paths into a data frame, but I am not sure how to do this inside RMarkdown and how to loop through it to build the slide titles and insert the images.
title <- c('pic_1', 'pic_2', 'pic_3', 'pic_4')
fpath <- c('modelA_pic_1.jpg', 'modelA_pic_2.jpg', 'modelA_pic_3.jpg', 'modelA_pic_4.jpg')
fpath <- paste0("../images/", fpath)
myfiles <- data.frame(title, fpath)
Updated Based on Accepted Answer
Below is what I ended up using for my Rmd. This page explains the basics of the xmpmulti package.
For this set up, my RMD is in one folder; the images are one folder up (../) and then in a folder called temp (../temp/). The images in this folder are named test-1.png, test-2.png, etc.
---
title: 'slideshow'
output:
beamer_presentation:
theme: "AnnArbor"
header-includes:
- \usepackage{xmpmulti}
---
# Introduction
## Blah
- Text
- Here
- Etc.
```{=latex}
\end{frame}
\section{Images}
\begin{frame}
\frametitle<1>{picture 1}
\frametitle<2>{picture 2}
\centering
\multiinclude[format=png,start=1,end=2,graphics={width=1\textwidth}]{../temp/test}
\end{frame}
\begin{frame}
```
some test

Assuming your images are named pic-1.png etc., then beamer has an automatic way to loop over the images via the xmpmulti package:
---
title: 'slideshow'
output:
beamer_presentation:
theme: "AnnArbor"
keep_tex: true
header-includes:
- \usepackage{xmpmulti}
---
# Introduction
## Blah
- Text
- Here
- Etc.
```{=latex}
\end{frame}
\section{Images}
\begin{frame}
\frametitle<1>{picture 1}
\frametitle<2>{picture 2}
\frametitle<3>{picture 3}
\centering
\multiinclude[format=png,start=1,end=3,graphics={width=.6\textwidth}]{pic}
\end{frame}
\begin{frame}
```
some test

Related

Rmarkdown: How to use code chunk from other Rmd file

How to use code chunk from child document in another Rmd file? I have one parent document named figures.Rmd which have following structure
`{r child='force.Rmd',echo=F,ref.label='pressure'}
`
some text
`{r child='force.Rmd',echo=F,ref.label='cars'}
and the child document named force.Rmd which have following structure
`{r, cars,echo=F}
options(knitr.duplicate.label = 'allow')
plot(cars)
`
`{r, pressure,echo=F}
options(knitr.duplicate.label = 'allow')
summary(pressure)
`
I want to read some chunks from the force.Rmd in the figures.Rmd. I am getting some output but it is producing the output 2 times. So basically I have 2 or 3 chunks in force.Rmd which I want to use at different places in figures.Rmd . How can I do that without getting the output 2 times?
This is parent.Rmd:
---
title: "parent"
author: "Me"
date: "2023-01-25"
output: html_document
---
## Parent
This is parent
## Some part of child
```{r echo=FALSE}
library(knitr)
invisible(knitr::purl("child.Rmd", output="temp", quiet=TRUE))
read_chunk("temp")
```
```{r ref.label='cars'}
```
## Some text
Here I am.
## Some other part of child
## Some part of child
```{r ref.label='pressure'}
```
```{r echo=FALSE}
unlink("temp")
```
This is child.Rmd
```{r cars}
summary(cars)
```
```{r pressure}
plot(pressure)
```
I can call each single child chunk at various positions:

plots after dynamic sections using R Markdown pander, knitr and pandoc

I use this rmd:
---
title: "Some Title"
author: "Some Author"
date: "`r format(Sys.time(), '%d-%m-%Y')`"
---
## A function that generates sections
```{r setup, include = FALSE}
library(pander)
create_section <- function() {
# Inserts "## Title (auto)"
pander::pandoc.header('Title (auto)', level = 2)
# Section contents
# e.g. a random plot
plot(sample(1000, 10))
# a list, formatted as Markdown
# adding also empty lines, to be sure that this is valid Markdown
pander::pandoc.p('')
pander::pandoc.list(letters[1:3])
pander::pandoc.p('')
}
```
## Generate sections
```{r, results='asis', echo=FALSE}
n_sections <- 3
for (i in seq(n_sections)) {
create_section()
}
```
and then:
library(knitr);
library(rmarkdown);
setwd("C:/bla")
knit('test_md.Rmd')
rmarkdown::pandoc_convert("test_md.md", to = "pdf", output = "test_pdf.pdf")
This kind of works but the plots are all rendered after the sections:
Each section should contain the plot. Any ideas? Thanks!
PS:
Wrapping:
plot(sample(1000, 10))
in print:
print(plot(sample(1000, 10)))
forces output to be produced. Unfortunately, NULL is also printed underneath the plot.
Could you just add pdf_document in the YAML and then generate the PDF by knitting?
---
title: "Some Title"
author: "Some Author"
date: "`r format(Sys.time(), '%d-%m-%Y')`"
output: pdf_document
---
I was able to get the same result you described when running the rmarkdown::pandoc_convert() on the .md file, all the plots at the end of the .PDF file.

Add Table of contents in different position in Rmd pdf

I want to add the table of content in different place instead of the first page in .Rmd pdf. I found the function render_toc() from #Garrick Aden-Buie this is the link https://gist.github.com/gadenbuie/c83e078bf8c81b035e32c3fc0cf04ee8. It is working perfect if I don't use cat() in chunk codes.
I have to use cat() in my .Rmd, is there any way I can add the table of contents any place in .Rmd
You can see the table of contents only test 1, test 2, and test 3, setosa, versicolor, virginica did not include in table of content
---
title: "test"
output:
pdf_document:
number_sections: yes
toc: yes
toc_depth: 4
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
source("render_toc.R")
library(knitr)
```
\newpage
# Table of Contents {#crazy-slug-here}
```{r echo = FALSE}
render_toc("test.Rmd")
```
# Test 1
# Test 2
# Test 3
```{r echo = FALSE, results ='asis'}
library(ggplot2)
for(Species in levels(iris$Species)){
cat('\n#', Species, '\n')
p <- ggplot(iris[iris$Species == Species,], aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point()
print(p)
cat('\n')
}
```
Using the code you provided I'm able to knit the pdf document and get the three plots, one for each Species in iris.
This code, however, produces two TOCs: one of them in the first page which is not desired according to your question. In order to get only the TOC produced by the function render_toc() set toc: no in the YAML header.
---
title: "test"
output:
pdf_document:
number_sections: yes
toc: no
toc_depth: 4
---
This way only one TOC will be generated and placed where render_toc() is.
Edit: After seeing your edit with the desired output, I think the following LaTeX code can help:
\newpage
\thispagestyle{plain}
\mbox{}
\setcounter{tocdepth}{2}
\renewcommand{\contentsname}{Table of Contents}
\tableofcontents
\newpage
\thispagestyle{plain}
\mbox{}
Note: here we are not using render_toc(). The code creates the TOC in the second page of the document. If you need another blank page, just introduce another block of:
\newpage
\thispagestyle{plain}
\mbox{}
These pages may or may not be numbered, which you control via the argument passed to \thispagestyle{}. See here for more details.
Full code:
---
title: "Document title"
output:
pdf_document:
number_sections: yes
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
\newpage
\thispagestyle{plain}
\mbox{}
\setcounter{tocdepth}{2}
\renewcommand{\contentsname}{Table of Contents}
\tableofcontents
\newpage
\thispagestyle{plain}
\mbox{}
# Test 1
## Subsection 1
# Test 2
## Subsection 2
# Test 3
```{r, results='asis', echo=FALSE}
library(ggplot2)
for(Species in levels(iris$Species)){
cat('\n#', Species, '\n')
p <- ggplot(iris[iris$Species == Species,],
aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point()
print(p)
cat("\n")
}
```
This way we end up with a TOC looking like this:

Cross references between slides and its content

In an R markdown presentation with output format beamer (to generate a LaTex/PDF file), is it possible to create cross-references between slides, i.e. pages of the final PDF?
This would be very helpful to quickly jump between slides, e.g. to navigate to an appendix at the end of the presentation.
I tried to use bookdown commands as proposed in this SO post, but without success.
MWE:
---
title: "Cross references between slides"
output:
# beamer_presentation: default
bookdown::pdf_book:
base_format: rmarkdown::beamer_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Bullets with references
- Bullet 1: \ref{tab:my-table}
- Bullet 2: \ref{fig:my-plot}
- Bullet 3: \ref{appendix}
## Bullets with references (bookdown)
- Bullet 1: \#ref(tab:my-table)
- Bullet 2: \#ref(fig:my-plot)
- Bullet 3: \#ref(appendix)
## table
```{r my-table, cars, echo = TRUE}
library(kableExtra)
kable(summary(cars))
```
## plot
```{r my-plot, pressure}
plot(pressure)
```
## appendix
my appendix
For linking to the appendix, you can use
- Bullet 3: \hyperlinkappendixstart{appendix}
If you examine the tex code produced by your MWE you will see that your table and figure are both included without caption or figure/table environment, but you can reference the slide they are on
- Bullet 1: \hyperlink{table}{table}
- Bullet 2: \hyperlink{plot}{plot}
MWE:
---
title: "Cross references between slides"
output:
beamer_presentation:
theme: "default"
keep_tex: true
includes:
in_header: preamble.tex
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Bullets with references
- Bullet 1: \hyperlink{table}{table}
- Bullet 2: \hyperlink{plot}{plot}
- Bullet 3: \hyperlinkappendixstart{appendix}
## table
```{r my-table, cars, echo = TRUE}
library(kableExtra)
kable(summary(cars))
```
## plot
```{r my-plot, pressure}
plot(pressure)
```
## appendix
\appendix
my appendix
Approach 2
or you could use the caption package to add captions to your tables and plots
---
title: "Cross references between slides"
output:
beamer_presentation:
theme: "default"
keep_tex: true
includes:
in_header: preamble.tex
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Bullets with references
- Bullet 1: \ref{foo}
- Bullet 2: \ref{bar}
- Bullet 3: \hyperlinkappendixstart{appendix}
## table
```{r my-table, cars, echo = TRUE}
library(kableExtra)
kable(summary(cars))
```
\captionof{table}{foo}
\label{foo}
## plot
```{r my-plot, pressure}
plot(pressure)
```
\captionof{figure}{bar}
\label{bar}
## appendix
\appendix
my appendix
using this as preamble.tex:
\setbeamertemplate{caption}[numbered]
\usepackage{caption}

hiding entire pages in an r markdown document

I have the r markdown document below. I would like to hide page 2 if parameter "P" is not equal to A.
So the result would be if parameter P != A then only 3 pages are produced.
Is this possible somehow?
---
title: "Untitled"
output:
pdf_document:
toc: yes
params:
P: A
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
\newpage
## PAGE2
this is text for page 2
this is text for page 2
```{r cars}
summary(cars)
```
\newpage
## PAGE3
this is text for page 3
```{r pressure, echo=FALSE}
plot(pressure)
```
\newpage
## PAGE4
this is text for page 4
You could comment the section out based on P value. Here is a bit of a hackish way to do it: surround the section with \iffalse/\fi. Note that the R code inside the section still needs to be valid for this to work (it will be compiled by knitr, but ignored by latex).
```{r, echo=FALSE, results='asis'}
if(params$P != "A")
cat("\\iffalse")
```
## PAGE2
this is text for page 2
this is text for page 2
```{r cars}
summary(cars)
```
\newpage
```{r, echo=FALSE, results='asis'}
if(params$P != "A")
cat("\\fi")
```

Resources