使用knitr有条件地显示Markdown文本块

18

我想编辑一个单独的rmarkdown(Rmd)文档,其中包含一系列“问题”,每个问题后面都跟着它的解决方案。每个解决方案可能包含R控制台的结果,但也可能包含一些说明(markdown和LaTeX格式的文本)。此外,我希望使用2个版本的knitr:有解决方案的版本和没有解决方案的版本,更改源代码尽可能少但也能编译。

我知道我可以使用逻辑变量以有条件地评估R代码并显示绘图和R输出,但是我不知道如何显示/隐藏(markdown和LaTeX格式的)文本块,除非我将所有文本都放入R字符向量中,但这对于保持清洁和可读性似乎很困难。

我找到了这个旧问题,

Conditionally display a block of text in R Markdown

其中提供了简单短文本的解决方法,该文本包含在R print()函数的参数中。

这个老问题,

insert portions of a markdown document inside another markdown document using knitr

是为了让父文档和子文档可以有条件地编译,但我不想把我的文档切成那么多片段。


哎呀,之前我写的东西你可以忘掉了。你想要控制文本的显示,而不是输出。嗯。 - TARehman
3个回答

30
你可以使用 asis 引擎在 knitr 中有条件地包含/排除任意文本,例如。
```{asis, echo=FALSE}
Some arbitrary text.

1. item
2. item

Change echo=TRUE or FALSE to display/hide this chunk.
```

但我刚刚发现了这个引擎中的一个漏洞并修复了它。除非您使用的是knitr >= 1.11.6,否则您可以自己创建一个简单的asis引擎。

```{r setup, include=FALSE}
library(knitr)
knit_engines$set(asis = function(options) {
  if (options$echo && options$eval) paste(options$code, collapse = '\n')
})
```
如果您想在文本中包含内联的 R 表达式,您将需要编织文本,例如:
```{r setup, include=FALSE}
library(knitr)
knit_engines$set(asis = function(options) {
  if (options$echo && options$eval) knit_child(text = options$code)
})
```

谢谢@Yihui,但是我想在这些文本块中包含R代码的内联评估,比如r 3+2,并直接看到结果(5)。当我将其包含在你的好例子中时,它不起作用 :( - PabloGregori
1
@PabloGregori 我更新了我的回答。 - Yihui Xie
@Yihui,非常好的答案!使用您的修复程序可以正常工作。只是注意到 ## title 没有按预期呈现,而 title\n=== 在 .Rmd 文件中和使用 rstudio 引擎时效果很好。 - aurelien
1
很棒的答案,即使四年后仍然有用。 - Shinra tensei
1
我确认八年后它仍然有用。 - undefined

5

有一种方法可以隐藏文档中的部分内容(包括文本和块):用html注释标记将它们注释掉。

还可以通过R在一个块中生成注释标记,根据在文档开头设置的变量。

```{r results='asis', echo=FALSE}
if (hide) {cat("<!---")}
```

```{r results='asis', echo=FALSE}
if (hide) {cat("-->")}
```

下面是一个完整可用的示例,可以通过设置 hide 变量为 FALSE 或 TRUE 来显示或隐藏文档的中间部分。这对于需要同时隐藏或显示多个部分的情况可能很有用,比如课程问题的解决方案。

---
title: "Untitled"
date: "15/10/2020"
output:
  word_document: default
  html_document: default
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
hide <- TRUE #TRUE to comment out part of the document, FALSE to show.
```

## Start

Always shown.

```{r}
hide
```

```{r results='asis', echo=FALSE}
if (hide) {cat("<!---")}
```

## To hide or not to hide

To be hidden or shown according to *hide* variable.

```{r}
"Also to be hidden according to 'hide' variable"
hist(rnorm(10))
```

```{r results='asis', echo=FALSE}
if (hide) {cat("-->")}
```

<!--
Never shown.
-->

## End

Always shown.

注意:在HTML输出中,隐藏部分被保留为注释,可以通过查看源代码来查看。另一方面,PDF(LaTex)和Word输出忽略HTML注释,隐藏部分不会包含在编织文档中。

因此,当隐藏部分应该是机密的时候(例如考试解决方案),应该使用PDF或Word输出而不是HTML。


0

对于那些在通过LaTex编织PDF时寻找解决方案的人,@Pere的答案对您无效(因为LaTex不理解<!--- -->这对符号表示注释)。

以下是一种可能的解决方法:

---
output:
  pdf_document
---

\newcommand{\ignore}[1]{}

```{r echo=FALSE}
include <- TRUE
```

```{r results='asis', echo=FALSE}
if(!include){cat("\\ignore{")}
```

Included bla bla

```{r results='asis', echo=FALSE}
if(!include){cat("}")}
```

```{r echo=FALSE}
include <- FALSE
```

```{r results='asis', echo=FALSE}
if(!include){cat("\\ignore{")}
```

NOT Included bla bla

```{r results='asis', echo=FALSE}
if(!include){cat("}")}
```

我的解决方案在转换为PDF时运行良好。LaTex不理解HTML注释,只会将其从编织文档中删除。实际上,这种解决方案在PDF或Word中的效果比在HTML中更好,因为隐藏部分不会出现在PDF或Word文档中,但可以在HTML源代码中作为注释找到。因此,如果您的隐藏部分应该是机密的,您只能将我的解决方案用于PDF或Word输出。 - Pere

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