如何在rmarkdown/knitr中按顺序输出部分(基于r)图形?

10
假设我有以下的R Markdown代码:
---
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)
```

在每个## Next点,我希望输出当前绘图的状态,以便逐步显示绘图的各个部分。我的最终目标是在一个ioslides演示文稿中创建连续的幻灯片,其中包含这些顺序绘图,所有内容都来自于上面的代码(但理想情况下,我不希望后面的代码影响前面的代码)。我希望它具有与我当前解决方法相同的效果:
---
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)))
```

输出的幻灯片如下所示:

Four slides

但是,可以看出这很笨拙,并且不太通用。解决方案的重要特点是绘图的代码行尽可能靠在一起,只写一次;理想情况下,我只需使用块选项/钩就可以完成这个过程。
最好的答案将保留回显添加到图形中的新代码行(例如,在## Next标记之间的代码),同时产生到该点的整个图形。
如何实现这一点?
编辑:此外,我希望能够对绘图进行分组更改,而不仅仅是将所有更改输出到新绘图中,因此fig.keep无法使用。

在文档中,您可以设置块选项 fig.keep = 'all',但如果您希望输出显示在不同的幻灯片上,则可能需要单独的代码块... - Gregor Thomas
问题在于 fig.keep 会给我四个图,而不是三个,因为它保留了所有的更改,而不仅仅是你想要的任意分组(已编辑以澄清此点)。 - richarddmorey
你看过类似问题的这个答案吗?由于该问题相当古老,所以我不知道它是否仍然相关。 - aosmith
2
非常好的问题!有更好的方法可以解决,但我刚刚发现了 knitr 中的一个错误。一旦我修复了这个错误,我会发布一个答案。 - Yihui Xie
2
“我刚刚发现了knitr中的一个bug。修复后,我会发布一个答案。” - 谢益辉 3小时前...看着答案,“3小时前回答-谢益辉”。那是超自然快速的错误修复,谢益辉!干得好! - Gregor Thomas
显示剩余2条评论
1个回答

8

选项fig.keep可以接受数字向量以索引图形,因此您可以通过fig.keep = 2:4选择最后三个图形(或通过fig.keep = -1删除第一个图形)。

要在不同幻灯片上分组绘图,您可以动态添加幻灯片标题。您可以使用带有选项results = 'asis'cat('\n\n## 标题\n\n'),或者使用knitr::asis_output()

以下是完整示例:

---
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)
```

注意,当前版本的knitr存在一个错误,我刚在Github上修复了它。目前你需要使用Github版本的knitr
if (packageVersion('knitr') <= '1.26')
  remotes::install_github('yihui/knitr')

1
太好了!我已经将它包含在我的模板中:https://github.com/richarddmorey/RcompileSlides/blob/master/inst/rmarkdown/templates/morey_presentation/skeleton/skeleton.Rmd,其中包括一个防止幻灯片编号递增的类。我可能还会实现自动从第一张幻灯片的标题中获取标题的javascript,这将避免每次都需要定义标题。但是这正是我想要的;谢谢。 - richarddmorey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接