Suppose I have the following rmarkdown code:
---
title: "Untitled"
author: "Author"
date: "04/12/2019"
output: ioslides_presentation
---
## Slide title
```{r echo=FALSE}
plot(1:10, axes = FALSE, ty = "n")
axis(1)
## Next
axis(2)
## Next
points(1:10, 1:10)
```
At each of the ## Next
points I would like to output the current state of the plot, so that I can sequentially reveal parts of the plot. My ultimate goal is to create subsequent slides in an ioslides
presentation with the sequential plots in them, all from the code above (with the caveat that ideally I would not want later lines of code to be able affect earlier ones, as could occur above).
I would like it to have the same effect as how I'm currently solving it:
---
title: "Untitled"
author: "Author"
date: "04/12/2019"
output: ioslides_presentation
---
```{r setup, include=FALSE}
## Set up environment for running the code
env <- new.env()
## Source code to run, as a list of quotes
full_src <- list(
quote({
plot(1:10, axes = FALSE, ty = "n")
axis(1)
}),
quote({
axis(2)
}),
quote({
points(1:10, 1:10)
})
)
```
## Slide title
```{r echo=FALSE}
# Evaluate first set of lines
eval(full_src[[1]], envir = env)
# Reset environment so later code can't affect earlier code
rm(list = ls(envir = env), envir = env)
```
## Slide title
```{r echo=FALSE}
# Evaluate first and second set of lines
invisible(sapply(1:2, function(i) eval(full_src[[i]], envir = env)))
# Reset environment so later code can't affect earlier code
rm(list = ls(envir = env), envir = env)
```
## Slide title
```{r echo=FALSE}
# Evaluate all lines
invisible(sapply(1:3, function(i) eval(full_src[[i]], envir = env)))
```
The slides that are output look like this:
But as you can see, that is clunky and not very general. Important features of a solution would be that the lines of code for the plot is as close together as possible, and only written once; ideally, I could just do this with a chunk option/hook.
The best kind of answer would retain the ability to echo the new lines of code added to the graph (e.g., the ones between the ## Next
markers) yet yield the whole plot up to that point.
What's the best way to achieve this?
Edit: Also, I want to be able to group changes to a plot, and not just output every to a new plot, so fig.keep
won't work.
The chunk option fig.keep
can take a numeric vector to index the plots, so you can choose the last three plots via fig.keep = 2:4
(or remove the first plot via fig.keep = -1
).
To group plots on different slides, you can dynamically add slide titles. You can either use cat('\n\n## Title\n\n')
with the chunk option results = 'asis'
, or with knitr::asis_output()
.
Below is a full example:
---
title: "Untitled"
author: "Author"
date: "04/12/2019"
output: ioslides_presentation
---
```{r, include=FALSE}
new_slide = function(title = '\n\n## Next\n\n') {
knitr::asis_output(title)
}
```
## Slide title
```{r echo=FALSE, fig.keep=2:4}
plot(1:10, axes = FALSE, ty = "n")
axis(1)
new_slide()
axis(2)
new_slide()
points(1:10, 1:10)
```
Note that there is a bug in the current version of knitr, which I just fixed on Github. For now you need to use the Github version of knitr:
if (packageVersion('knitr') <= '1.26')
remotes::install_github('yihui/knitr')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With