How to include a header based on a condition in knitr - r

I have a header followed by a code chunk in an Rmd file. I only want to include this header and the chunk followed by it, if a condition is met. I know how to do that with the chunk, since it's in the body of the code, but how do I do the former?
```{r}
print_option <- TRUE
```
## My header
```{r}
if(print_option==TRUE) {
print (x)
}
```

The chunk option eval and asis_output() provide a simple solution.
Assuming that print_option is a boolean indicating whether to show the header (and whether to execute other code like print(1:10) in chunk example1):
```{r setup}
library(knitr)
print_option <- TRUE
```
```{r, eval = print_option}
asis_output("## My header\\n") # Header that is only shown if print_option == TRUE
print(1:10) # Other stuff that is only executed if print_option == TRUE
```
Text that is shown regardless of `print_option`.
```{r setup2}
print_option <- FALSE
```
Now `print_option` is `FALSE`. Thus, the second header is not shown.
```{r, eval = print_option}
asis_out("## Second header\\n")
```
Output:
For longer conditional outputs (of text/markdown, without embedded R code) the engine asis can be helpful, see this answer (it's long, but the solution at the end is very concise).
Addendum
Why is ## `r Title` with Title set to "My header" or "" as suggested in this answer a bad idea? Because it creates an "empty header" in the second case. This header is not visible in the rendered HTML/markdown output, but it is still there. See the following example:
```{r, echo = FALSE}
title <- ""
```
## `r title`
This generates the following markdown ...
##
... and HTML:
<h2></h2>
Besids being semantically nonsense it might lead to layout issues (depending on the style sheet) and disrupts the document outline.

I figured it out :)
```{r, echo=FALSE, include=FALSE}
x<- FALSE
if ( x ) {
Title <- "My header"
} else {Title=""}
```
## `r Title`
```{r, echo=FALSE}
if(x) {
print(1:10)
}
```

Related

quarto rmarkdown code block to only display certain lines

I have a .qmd / .rmd file that wants to show the output of block of code. The code block has a lot of lines at the beginning that I'd like to hide, in the example below I'd like the output to be the third line of code str(month) and output the result of str(month). I've attempted to edit the code block parameters, but it's giving me an error:
---
format:
html: default
---
```{r}
#| echo: c(3)
month <- "July"
str(month)
```
Error:
7: #| echo: c(3)
~~~
8: month <- "July"
x The value c(3) is string.
i The error happened in location echo.
rmarkdown support files suggest something like this might be possible
This does not work because you are using YAML syntax for chunk options as recommended with Quarto but #| echo: c(3) is not valid YAML. #| echo: 3 is.
You can use !expr within YAML field to parse R code if necessary. #| echo: !expr c(3) would work. It is explained here: https://quarto.org/docs/computations/r.html#chunk-options
However, know that knitr supports other way to specify chunk options:
Usual header where option needs to be valid R code
```{r, echo = c(3)}
#| echo: c(3)
month <- "July"
str(month)
```
And a multiline version of it, useful when having long option like fig.cap
```{r}
#| rmdworkflow,
#| echo = FALSE,
#| fig.cap = "A diagram illustrating how an R Markdown document
#| is converted to the final output document.",
#| out.width = "100%"
knitr::include_graphics("images/workflow.png", dpi = NA)
```
See the announced in blog post for more about this new syntax: https://yihui.org/en/2022/01/knitr-news/
This question has also been asked in Github - so more detailed answer there: https://github.com/quarto-dev/quarto-cli/issues/863
I don't know if I understood the question correctly. But you can choose to display only the code you want based on the index of the line inside specific chunk. Insert the number of index line you want to show inside the c() {r, echo = c()}
Your specific case
---
format:
html: default
---
```{r, echo = c(2)}
month <- "July"
str(month) # line 2
```
Other Example:
---
format:
html: default
---
```{r, echo = c(5,8)}
# Hide
month <- "July"
## Show code and output
str(month) # Line 5
## Show code and output
1+1 # Line 8
## Show just output
2+2
```

Pass Params from loop to generate Dynamic Reports in Rmarkdown

Im new to Rmarkdown and I would like to create dynamic reports where every report section is generated from a template (child) document. Each section will then start with a newpage in the rendered pdf.
My approach is currently based on this post which shows how to generate dynamically text in the child (which works), however I am not able to transfer the contents of the loop into a R-Codeblock, probably because the params are not well defined in the way that I tried to do it.
This is how my parent document looks like:
---
title: "Dynamic RMarkdown"
output: pdf_document
---
```{r setup, include=FALSE}
library("knitr")
options(knitr.duplicate.label = "allow")
```
# Automate Chunks of Analysis in R Markdown
Blahblah Blabla
\newpage
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in as.character(unique(iris$Species))) {
out = c(out, knit_expand('template.Rmd'))
params <- list(species = i)
}
```
`r paste(knit(text = out), collapse = '\n')`
and this is how the child looks like
---
title: "template"
output: html_document
params:
species: NA
---
# This is the reporting section of Species {{i}}
This is a plot of Sepal length and width based on species {{i}}.
```{r plot2}
paste(params$species)
# plot doesnt work work
# plot(iris$Sepal.Length[iris$Species=={{i}}],
# iris$Sepal.Width[iris$Species=={{i}}]
# )
```
\newpage
To my understanding the parameter that is actually passed is the last species from the dataset generated in the loop but I'm not sure why the plot would't work then. Can anybody help me out on how to fix this issue?
Ok. No need to go through params. The solution was simply to put i between brackets AND parenthesis in the child-document.
Parent:
---
title: "Dynamic RMarkdown"
output: pdf_document
---
```{r setup, include=FALSE}
library("knitr")
options(knitr.duplicate.label = "allow")
```
# Automate Chunks of Analysis in R Markdown
Blahblah Blahblah Main text before individual sections
\newpage
```{r run-numeric-md, include=FALSE}
out = NULL
for (i in as.character(unique(iris$Species))) {
out = c(out, knit_expand('template.Rmd'))
}
```
`r paste(knit(text = out), collapse = '\n')`
Child
---
title: "template"
output: html_document
---
# This is the reporting page of Species {{i}}
This is a plot of Sepal length and width based on species {{i}}.
```{r plot2}
paste("This will be a plot of Sepal Length and Witdh from", '{{i}}')
plot(iris$Sepal.Length[iris$Species=='{{i}}'],
iris$Sepal.Width[iris$Species=='{{i}}']
)
```
\newpage
Original solution found here.

Is there a way to specify a global options chunk function in Rmarkdown so that only some of the graphs will show/not show by toggling the command?

I currently have a subset of figures in Rmarkdown but would like to hide or display them by specifying echo = F or echo = T for those only. It is tedious to go through each of the figures I want to hide or display and change the echo option. Is there a global way of toggling or making certain figures show? In other words, is there a way to perhaps do:
```{r, echo.func}
include.graphics("this/plot/shows.jpg")
```
and be able to somehow control echo.func to be equal to echo = F or echo = T in the beginning? Thanks!
The argument to echo= can be a full expression, so you can define classes or individual blocks. Something like this:
---
title: echo test
output: html_document
---
```{r setup, echo = FALSE, include = FALSE}
echolist <- c("plots", "table2")
```
```{r table1, echo = any(c("tables", "table1") %in% echolist)}
# mtcars[1:3,]
```
```{r plot1, echo = any(c("plots", "plot1") %in% echolist)}
# plot(1)
```
```{r table2, echo = any(c("tables", "table2") %in% echolist)}
# mtcars[5:10,]
```
```{r plot2, echo = any(c("plots", "plot2") %in% echolist)}
# plot(2)
```
From this, I think it'd be feasible to write a function that you pass the block name (e.g., {r blockname, echo=checkecho("blockname")}), and internally it does something that perhaps checks literal titles, patterns, groups, etc.
Suggestion for functionizing it:
---
title: echo test
output: html_document
---
```{r setup, echo = FALSE, include = FALSE}
.checkecho <- function(nm) {
any(c(nm, gsub("\\d+$", "s", nm)) %in% c("plots", "table2"))
}
```
```{r table1, echo = .checkecho("table1")}
# mtcars[1:3,]
```
```{r plot1, echo = .checkecho("plot1")}
# plot(1)
```
```{r table2, echo = .checkecho("plot2")}
# mtcars[5:10,]
```
```{r plot2, echo = .checkecho("table2")}
# plot(2)
```
The biggest take-away from this is for you to come up with a naming standard that will facilitate your job. In this example:
everything starts with a simple description of expected output and ends with a number (which does not need to be incrementing *shrug*);
you can control individual echo-ing by specifying specific blocks or by removing the number and adding an "s"
You can easily turn this into a negation policy instead, where you turn off specific elements ... the possibilities are numerous and probably why there is not already a function in rmarkdown or knitr that facilitates this.
(If you're curious ... I chose to start the function name with a dot so that, if for some reason you include the output from ls() in your report, the function will not be included. To see it, you'd need to do ls(all.names=TRUE). *shrug*)

Replace variables with their corresponding values in source code chunk

I'd like to show parameter values and not params$... in R Markdown output. For example, the first code chunk below displays params$file in the output, but I'd like to replace that with samples.txt. I tried adding a second chunk with message, but that outputs a white code chunk and I'd like a gray background like all other R code blocks.
---
output: html_document
params:
file: samples.txt
---
```{r read, message=FALSE, collapse=TRUE, comment=""}
x <- read_tsv(params$file)
x
```
This just needs a gray background
```{r print, echo=2, collapse=TRUE, comment=""}
message('x <- read_tsv("', params$file, '")')
x
```
You could modify the source hook. A solution tailored to your need follows immediately. For a more general approach, that replaces all elements in params, scroll down.
---
output:
pdf_document: default
html_document: default
params:
file: samples.txt
---
```{r, include=FALSE}
library(knitr)
library(stringr)
default_source_hook <- knit_hooks$get('source')
knit_hooks$set(source = function(x, options) {
x <- str_replace_all(x, pattern = 'params\\$file', paste0("'",params$file,"'"))
default_source_hook(x, options)
})
```
```{r print, echo=T, comment="", eval = T}
print(params$file)
```
First we save the default hook that would be used depending on the output file type (render_html or render_latex etc.). Then we change the source hook: we replace all occurrences of params$file with its value and then throw the source code back into the default hook we saved before.
In this case this results in:
This magic works, because we only modify the source code that will be printed, not the one being evaluated!
Update: A more general Approach
I played a bit with your example and created a more general hook. It should replace all elements of the form params$... in your code chunks. It even checks for the type of value and adds quotes if it is a character value.
Check the following MRE:
---
output:
pdf_document: default
html_document: default
params:
file: samples.csv
age: 28
awesome: true
34: badname
_x: badname
---
```{r, include=FALSE}
library(knitr)
library(gsubfn)
default_source_hook <- knit_hooks$get('source')
knit_hooks$set(source = function(x, options) {
x <- gsubfn(x = x, pattern = "params\\$`?([\\w_]+)`?", function(y) {
y <- get(y, params)
ifelse(is.character(y), paste0("'", y, "'"), y)
})
default_source_hook(x, options)
})
```
```{r print, echo=T, comment="", eval = T}
file <- params$file
age <- params$age
awsm <- params$awesome
# dont name your variables like that! works though...
badexmpls <- c(params$`34`, params$`_x`)
```
We make use of gsubfn(). This function allows us to use a function for the replacement attribute (not possible in common gsub). This function takes on the elements found, but, thanks to regex only the part after the $. So in this chunk, y equals file, age and awesome.

How to use htmltools::tagList such that headers show in RMarkdown table of contents

I need to generate multiple htmlwidgets within a loop in an RMarkdown document. This is accomplished using htmltools::tagList. The following snippet will generate HTML output with 2 level 2 headings and a datatable in each section. The only problem is that I specified toc: true but though tags$h2(headers[i]) will render a level 2 headings on the page, those headings are not picked up by the table of contents. Is there a way get these headings in the TOC?
---
output:
html_document:
toc: true
---
## level 2 heading 0 - this one in TOC
```{r}
library(DT)
library(htmltools)
headers <- c("level 2 heading 1", "level 2 heading 2")
html_tags <- vector(mode = "list", length = 2*length(headers))
for (i in 1:length(headers)) {
html_tags[[(2*i)-1]] <- tags$h2(headers[i])
html_tags[[(2*i)]] <- list(list(datatable(iris)))
}
tagList(html_tags)
```
Note that in the result below the heading generated using "##" shows up in the table of contents, but the headings from the tagList call, though they render correctly in the document, are now in the table of contents.
Try this:
---
output:
html_document:
toc: true
---
```{r, echo=FALSE, message=FALSE, warning=FALSE}
library(DT)
library(htmltools)
```
```{r ,include = FALSE}
DT::datatable(iris)
```
## level 2 heading 0 - this one in TOC
```{r echo=FALSE, message=FALSE, warning=FALSE, results = 'asis'}
for (i in 1:2){
cat(" \n## level 2 heading", i, " \n")
print(htmltools::tagList(DT::datatable(iris)))
cat(" \n")
}
```
And the result is:
Maybe this is what you actually want.
Remember: You should avoid headers <- c("level 2 heading 1", "level 2 heading 2").
If you need hundred or thousand of headers, this isn't efficient and must waste too much time.

Resources