Programmatically generate slides in R with xaringan and plotly - r

I recently started using xaringan and it's really neat. Thanks Yihui for the great package. One question I was wondering, is it possible to programmatically generate slides, each containing a plotly plot, in a for loop? I know I can generate slides of ggplots like this, where ggplot_list is a list of ggplots:
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
print(p)
}
```
This works perfectly.
I can also include individual plotly plots by calling ggplotly(ggplot_list[[1]]), which also works perfectly.
But I can't seem to get the combination of the two to work, naively doing the following generates empty slides for me.
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
ggplotly(p)
}
```
Update: here I include a minimal example of things I've tried so far.
---
title: "xaringan + plotly + loop?"
subtitle: "Does it work?"
author: "Fenfen Kan"
date: "2017/13/32"
output:
xaringan::moon_reader:
lib_dir: libs
nature:
highlightStyle: github
highlightLines: true
countIncrementalSlides: false
---
```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
```
# Several boring ggplots
```{r, message=FALSE, warning=FALSE}
library(ggplot2)
library(plotly)
p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
geom_point(aes(color=Species))
p2 <- ggplot(iris, aes(Petal.Length, Petal.Width)) +
geom_point(aes(color=Species))
p3 <- ggplot(iris, aes(Sepal.Length, Petal.Length)) +
geom_point(aes(color=Species))
ggplot_list <- list(p1, p2, p3)
```
---
# Invididual plotly works
```{r}
ggplotly(p1)
```
---
# ggplot slides in loop also works
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
print(p)
}
```
---
# plotly in loop doesn't work
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
ggplotly(p)
}
```
# print(ggplotly(p)) in loop doesn't work either
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
print(ggplotly(p))
}
```

I figured out a solution when trying to do a similar thing in knitr recently. I added it to the above example. See the last section - It generates 3 plotly slides in a loop.
---
title: "xaringan + plotly + loop?"
subtitle: "Does it work?"
author: "Fenfen Kan"
date: "2017/13/32"
output:
xaringan::moon_reader:
lib_dir: libs
nature:
highlightStyle: github
highlightLines: true
countIncrementalSlides: false
---
```{r setup, include=FALSE}
options(htmltools.dir.version = FALSE)
```
# Several boring ggplots
```{r, message=FALSE, warning=FALSE}
library(ggplot2)
library(plotly)
library(knitr)
p1 <- ggplot(iris, aes(Sepal.Length, Sepal.Width)) +
geom_point(aes(color=Species))
p2 <- ggplot(iris, aes(Petal.Length, Petal.Width)) +
geom_point(aes(color=Species))
p3 <- ggplot(iris, aes(Sepal.Length, Petal.Length)) +
geom_point(aes(color=Species))
ggplot_list <- list("p1"=p1, "p2"=p2, "p3"=p3)
```
---
# Invididual plotly works
```{r}
ggplotly(p1)
```
---
# ggplot slides in loop also works
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
print(p)
}
```
---
# plotly in loop doesn't work
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
ggplotly(p)
}
```
# print(ggplotly(p)) in loop doesn't work either
```{r, message=FALSE, warning=FALSE, results='asis'}
for (p in ggplot_list) {
cat("\n\n---\n")
print(ggplotly(p))
}
```
# generate chunks, then explicitly calling `knit` works!
```{r create-markdown-chunks-dynamically, include=FALSE}
out = NULL
for (p_name in names(ggplot_list)) {
knit_expanded <- paste0("\n\n---\n## Plot: ", p_name, "\n\n```{r results='asis', echo=FALSE, warning=FALSE, message=FALSE}\n\nggplotly(ggplot_list[['", p_name, "']])\n\n```")
out = c(out, knit_expanded)
}
```
<!--- knit those table chunk statements -->
`r paste(knit(text = out), collapse = '\n')`

Related

Stop ## quartz_off_screen showing in HTML report

My R Markdown files contain code to save PDF files e.g.
pdf(paste0("plots/filtering/", exp_name, "_umap.pdf"))
walk(list(p4, p5, p6, p7), print)
dev.off()
When I knit to HTML, I get the following printed as part of the HTML.
## quartz_off_screen
## 2
Is there a way to prevent this? I already have the knitr chunk options message and warning set to FALSE.
Best wishes,
Lucy
Wrap the the call to dev.off with invisible(...).
MWE
---
title: "Test"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ggplot2)
library(purrr)
```
## R Markdown
```{r}
p1 <- ggplot(mtcars, aes(mpg, disp)) + geom_point()
p2 <- ggplot(mtcars, aes(mpg, disp, color = factor(vs))) + geom_point()
```
```{r}
pdf("mtcars.pdf")
walk(list(p1, p2), print)
invisible(dev.off())
```

R markdown: how to insert space between images

I want to add two images side by side in R markdown, but with some space between them.
How can I adjust the space between the images? Thank you!
![](/Users/filename/black.png){width=50%}
![](/Users/filename/gray.png){width=50%}
One option could be using ggdraw() + draw_image from {cowplot}
---
title: "Untitled"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r side_by_side, fig.align='center'}
library(cowplot)
ggdraw() +
draw_image("test_logo.png", width = 0.4) +
draw_image("test_animal.jpg", width = 0.4, x = 0.5)
```
Which looks like
Another option could be making white border for the images using image_border from the {magick} package so that even if there is no actual space between them, white border will look like a space.
```{r another_option, warning=FALSE, message=FALSE}
library(magick)
img1 <- image_read("test_logo.png")
bordered_img1 <- image_border(img1, "white", "20x20")
img2 <- image_read("test_animal.jpg")
bordered_img2 <- image_border(img2, "white", "20x20")
image_write(bordered_img1, "img1.png")
image_write(bordered_img2, "img2.jpg")
```
```{r side_img, out.width="50%"}
knitr::include_graphics(c("img1.png", "img2.jpg"))
```
Which looks like,

knitr cache and ggplot2::last_plot()

Is there a way of make it so that knitr caches stuff so that last_plot() works properly? For example this document:
---
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, cache = TRUE)
library(ggplot2)
```
```{r cars}
ggplot(mtcars, aes(hp, mpg)) +
geom_point()
```
The first value is `r last_plot()$data$mpg[1]`
The first time is generated, it will have one figure and the text "The first value is 21". But the second time, the last inline code will fail.

How to specify theme in Rmarkdown notebook depending on output format?

How do I tell to knitr to use theme_classic if I export my Rmd notebook to PDF and use dark_theme_gray from ggdark package if I export my Rmd notebook to HTML?
Try this. (Sorry. I had no ggdark installed. So I just used theme_gray for HTML output). knitr provides helper functions to check for is_html_output or is_latex_output.
---
title: "test"
output:
pdf_document: default
html_document: default
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Plot
```{r}
library(ggplot2)
p <- ggplot(mtcars, aes(hp, mpg)) +
geom_point()
if (knitr::is_html_output()) {
p + theme_gray()
} else if (knitr::is_latex_output()) {
p + theme_classic()
}
```

cite figure in other figure caption in markdown to pdf

Using R markdown with PDF output, I want to cite a figure into another figure caption. I also want to cite a BibTex reference in the caption. Any ideas? Here's an example of code:
---
title: "Untitled"
author: "me"
date: "today"
output:
pdf_document:
latex_engine: lualatex
number_sections: no
linestretch: 1.5
bibliography: input/Library.bib
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
```
```{r}
df <- mtcars
library(ggplot2)
```
```{r, fig.cap="some stuff"}
ggplot(df, aes(cyl, mpg)) + geom_point()
```
```{r, fig.cap="some more stuff. here I'd like to cite figure 1. I would also like a BibTex citation"}
ggplot(df, aes(cyl, hp)) + geom_point()
```
In my experience cross-referencing works better when one uses bookdown::pdf_document2 or bookdown::html_document2. Note that it makes sense to name the chunk that produces the figure since that name is used in the label used for referencing:
---
title: "Untitled"
author: "me"
date: "today"
output:
bookdown::pdf_document2:
latex_engine: lualatex
number_sections: no
bookdown::html_document2:
default
linestretch: 1.5
bibliography: packages.bib
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE)
knitr::write_bib(c(.packages()), 'packages.bib')
```
```{r}
df <- mtcars
library(ggplot2)
```
```{r stuff, fig.cap="some stuff"}
ggplot(df, aes(cyl, mpg)) + geom_point()
```
```{r, fig.cap="some more stuff. here I'd like to cite figure \\#ref(fig:stuff). I would also like a BibTex citation [#R-base]"}
ggplot(df, aes(cyl, hp)) + geom_point()
```
For the BibTeX reference I am using an automatically created one, but the adaption to your case should be obvious.

Resources