Animated figures

If a chunk prints multiple graphs, the graphs can be converted into steps in an animation. This only works if ffmpeg is installed.

Step 1) Copy the text from the box below and paste it on to the end of your Markdown document and press “Knit HTML”.

## Animated figures

```{r,  fig.show='animate', fig.width=5, fig.height=4}
library(ggplot2)
for (count in 1:4) {
  n <- 10 ^ count
  x <- data.frame(var = rnorm(n))
  print(ggplot(x) +
    geom_histogram(aes(x = var), binwidth = 0.2) +
    ggtitle(paste('n =', n)))
}
```
            

Animated figures

library(ggplot2)
for (count in 1:4) {
  n <- 10 ^ count
  x <- data.frame(var = rnorm(n))
  print(ggplot(x) +
    geom_histogram(aes(x = var), binwidth = 0.2) +
    ggtitle(paste('n =', n)))
}

Caching

A potential downside of combining code used to analyse data and notes/interpretation is that every time you rerun the RMarkdown document to make a small change (e.g. add or update notes), all of the code is run again even if no changes to the code are made. For analyses that take a long time, this can make using RMarkdown impractical. Fortunately, there is a feature called caching that allows the results of each chunk to be saved independently and reused if no changes are made to that chunk. Setting the chunk option cache to TRUE will mean that after a code chunk is run for the first time it will not need to be run again unless it changes.

Below is an example of code to draw a Barnsley Fern borrowed from an RPub by Kui-Ming Chen.

Step 2) Copy the text from the box below and paste it on to the end of your Markdown document and press “Knit HTML”. It should take at least a few seconds extra to draw the complicated graph. Once it is done, press “Knit HTML” again. It should take nearly the same amount of time as it had before adding the graph. Now, change the value of the “iter” variable on the first line to something else near 10000 and press “Knit HTML” again. Since the code has changed, it should once again take more time to remake the graph.

## Caching

```{r, cache=TRUE}
iter <- 10000
p <- runif(iter)
coord <- matrix(c(0, 0), ncol = 1)
df <- rbind(data.frame(), t(coord))
for (i in 1:iter) {
    if (p[i] <= 0.05) {
        m <- matrix(c(0, 0, 0, 0.16), nrow = 2, ncol = 2)
        const <- matrix(c(0, 0), ncol = 1)
    } else if (p[i] > 0.05 && p[i] <= 0.86) {
        m <- matrix(c(0.85, -0.04, 0.04, 0.85), nrow = 2, ncol = 2)
        const <- matrix(c(0, 1.6), ncol = 1)
    } else if (p[i] > 0.86 && p[i] <= 0.93) {
        m <- matrix(c(0.2, 0.23, -0.26, 0.22), nrow = 2, ncol = 2)
        const <- matrix(c(0, 1.6), ncol = 1)

    } else {
        m <- matrix(c(-0.15, 0.26, 0.28, 0.24), nrow = 2, ncol = 2)
        const <- matrix(c(0, 0.44), ncol = 1)
    }
    coord <- m %*% coord + const
    df <- rbind(df, t(coord))
}

plot(x = df[, 2], y = df[, 1], plt = c(0, 10, -5, 5), cex = 0.1, asp = 1)
```
            

Caching

iter <- 10000
p <- runif(iter)
coord <- matrix(c(0, 0), ncol = 1)
df <- rbind(data.frame(), t(coord))
for (i in 1:iter) {
    if (p[i] <= 0.05) {
        m <- matrix(c(0, 0, 0, 0.16), nrow = 2, ncol = 2)
        const <- matrix(c(0, 0), ncol = 1)
    } else if (p[i] > 0.05 && p[i] <= 0.86) {
        m <- matrix(c(0.85, -0.04, 0.04, 0.85), nrow = 2, ncol = 2)
        const <- matrix(c(0, 1.6), ncol = 1)
    } else if (p[i] > 0.86 && p[i] <= 0.93) {
        m <- matrix(c(0.2, 0.23, -0.26, 0.22), nrow = 2, ncol = 2)
        const <- matrix(c(0, 1.6), ncol = 1)

    } else {
        m <- matrix(c(-0.15, 0.26, 0.28, 0.24), nrow = 2, ncol = 2)
        const <- matrix(c(0, 0.44), ncol = 1)
    }
    coord <- m %*% coord + const
    df <- rbind(df, t(coord))
}

plot(x = df[, 2], y = df[, 1], plt = c(0, 10, -5, 5), cex = 0.1, asp = 1)

There are subtle issues that can occur when mixing cached and uncached chunks that reference the same variables, so you should learn more about the details of how caching works before relying on it too heavily.