Conditionally display block of markdown text using knitr
Asked Answered
C

3

18

I would like to edit a single rmarkdown (Rmd) document with a list of "problems", each followed by its solution. Each solution may contain the results of the R console, but also some explaining (markdown and LaTeX formatted) text. Besides, I would like use knitr in 2 versions: with and without the solutions, changing the source as less as possible, and compiling.

I know that I can use a logical variable in order to conditionally evaluate R code and show plots and R output, but I don't know how to show/hide blocks of (markdown and LaTeX) formatted text, unless I put all that text into R character vectors, which seems hard for keeping things clean and readable.

I found this old question,

Conditionally display a block of text in R Markdown

where the solution was given for simple short text, which was included as an argument of the R print() function.

This other old question,

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

was for having a father document and child documents which were conditionally compiled, but I don't want to slice my document into so many pieces.

Costanzia answered 5/10, 2015 at 9:0 Comment(1)
Whoops. Forget what I wrote before. You want to control the display of text, not output. Hmm.Sadonia
P
31

You could use the asis engine to conditionally include/exclude arbitrary text in knitr, e.g.

```{asis, echo=FALSE}
Some arbitrary text.

1. item
2. item

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

If you want to include inline R expressions in the text, you will have to knit the text, e.g.

```{r setup, include=FALSE}
library(knitr)
knit_engines$set(asis = function(options) {
  if (options$echo && options$eval) knit_child(text = options$code)
})
```
Percolator answered 5/10, 2015 at 21:15 Comment(8)
Thanks @Yihui, but I would like to include inline evaluations of R code, such as r 3+2, in those text blocks and see directly the result (5). It doesn't work when I include it in your nice example :(Costanzia
@Costanzia Updated my answer.Percolator
@Yihui, great answer! Works fine with your fix. Just noticed that ## title is not rendered as intended, while title\n=== works nicely in the .Rmd file and using the rstudio engine.Wommera
Great answer, still useful 4 years laterSherleysherline
I confirm that it is still useful 8 years laterAscariasis
knit_child was the key. In fact, you could even include r code chunks within asis environments. To do so, use more than 3 backticks, eg. ````{asis} Here is a sample code ```{r} # r code here ``` ````Psalmist
@Psalmist Yes! I'm glad you figured it out.Percolator
@YihuiXie perhaps this could be included in the rmarkdown cookbook?Psalmist
S
6

There is a way to hide parts of the document (including text and chunks): to comment them out with html comment marks.

And comment marks can be generated by R in a block according to a variable that can be set at the beginning of the document.

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

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

And just to show a complete working example, in the example below the middle section of the document can be shown or hidden by setting the hide variable to FALSE or TRUE. That might be useful in case there are several sections to hide or show at once - for example, solutions of course problems.

---
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.

Just a caveat: in html output the hidden parts are kept as comments and can be seen just by viewing the source. On the other hand, PDF (LaTex) and Word outputs ignore html comments and the hidden parts aren't included in the knitted documents.

Therefore, when the hidden parts are supposed to be somehow confidential (e.g. exam solutions) PDF or Word output should be used instead of html.

Schaumberger answered 14/10, 2020 at 22:52 Comment(0)
K
0

For those looking for a solution when knitting to pdf through LaTex, the answer from @Pere won't work for you (because LaTex doesn't understand the <!--- --> pair as indicating a comment).

Below is one possible workaround:

---
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("}")}
```
Kayleen answered 5/12, 2022 at 15:53 Comment(1)
My solution does work fine when knitting to PDF. LaTex doesn't understand html comments and just removes them from the knitted document. In fact this solution works better with PDF or Word than with html because the hidden parts aren't present in the PDF or the Word document, but they can be found in the html source as comments. Therefore, if your hidden part is supposed to be confidential, you can use my solution only with PDF or Word outputs.Schaumberger

© 2022 - 2024 — McMap. All rights reserved.