4

The following R-Markdown code doesn’t work with Knitr:

Create a bimodal toy distribution.

```{r}
a = c(rnorm(100, 5, 2), rnorm(100, 15, 3))
```

Set up the graphics device.

```{r fig.show='hide'}
plot(0, type = 'n', xlim = c(0, 20), ylim = c(0, 0.2), axes = FALSE)
```

Plot the density.

```{r}
polygon(density(a), col = 'black')
```

Knitr assumes that a graphics device ends at the end of an R code block, and closes the device. Consequently, I cannot reuse (in the third code block) a previously set up graphics device.

My question is simple: how can I make this work?

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214

3 Answers3

3

You can preserve the previous plot via recordPlot(), and redraw it with replayPlot(). This can be done in a custom chunk hook function. Here is a quick example:

```{r setup}
library(knitr)
knit_hooks$set(plot.reuse = local({
  last = NULL
  function(before, options) {
    if (!isTRUE(options$plot.reuse)) {
      last <<- NULL
      return(NULL)
    }
    if (before) {
      if (inherits(last, 'recordedplot')) replayPlot(last)
    } else {
      last <<- recordPlot()
    }
    return(NULL)
  }
}))
```

Draw a plot.

```{r test-a, plot.reuse=TRUE}
plot(cars)
```

Add a line to the previous plot:

```{r test-b, plot.reuse=TRUE}
abline(lm(dist~speed, data=cars))
```

You can also use the undocumented feature opts_knit$set(global.device = TRUE) so that the whole document always uses the same graphical device, which is never closed. I have never mentioned this feature in the public although it has been there for two years, because I have not thought carefully about the possible unexpected consequences of this approach.

Yihui Xie
  • 28,913
  • 23
  • 193
  • 419
1

This is not really the solution but a workaround: I am using ggplot, so I am able to store a plot in a variable. As variables are shared across code blocks one may re-use partially complete objects in subsequent code blocks.

Artem Fedosov
  • 2,163
  • 2
  • 18
  • 28
-2

From my understanding, the first plot is independent to the second one.

```{r}
plot(0, type = 'n', xlim = c(0, 20), ylim = c(0, 0.2), axes = FALSE)
polygon(density(a), col = 'black')
```
chee.work.stuff
  • 326
  • 2
  • 14