Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create RMarkdown headers and code chunks in purrr

Tags:

r

r-markdown

The following .Rmd is what I think should produce what I'm looking for:

---
title: "Untitled"
date: "10/9/2021"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)

full_var <- function(var) {
  cat("### `", var, "` {-} \n")
  cat("```{r}", "\n")
  cat("print('test')", "\n")
  cat("```", "\n")
}

vars <- c("1", "2", "3")
```

```{r results = "asis"}
purrr::walk(vars, full_var)
```

Instead, it looks like:

example

Why is the print('test') not being evaluated and instead being presented as a code block?

like image 398
Dylan Russell Avatar asked Dec 30 '22 12:12

Dylan Russell


1 Answers

Solution

If you render your code as well as the results of running your code in a result='asis' chunk I think you can manage what you're after. You can do this by taking advantage of knitr's knit() function as follows:

---
title: "Untitled"
date: "10/9/2021"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)

full_var <- function(var) {
  
  # Define the code to be run
  my_code <- "print('test')"
  
  # Print the code itself, surrounded by chunk formatting
  cat("### `", var, "` {-} \n")
  cat("```{r}", "\n")
  cat(my_code, "\n")
  cat("``` \n")
  
  # Use knitr to render the results of running the code.
  # NB, the use of Sys.time() here is to create unique chunk headers,
  # which is required by knitr. You may want to reconsider this approach.
  cat(knitr::knit(
    text = sprintf("```{r %s}\n%s\n```\n",  Sys.time(), my_code), 
    quiet = TRUE
  ))
}

vars <- c("1", "2", "3")
```

```{r results = "asis"}
purrr::walk(vars, full_var)
```

This produces output like the following: Code output

Details: How knitr works

When knitr renders an R Markdown file it does so in the following stages:

  1. knitr generates a plain markdown file from your original .Rmd. This is when things like the yaml header and chunk options get used, and is crucially when your R code gets run
  2. pandoc converts the markdown file into the final output. Exactly what happens here depends on what output format you're using.

How knitr works

Using results='asis'

The chunk option results = 'asis' simply changes what the intermediate markdown script will look like in the rendering process. For example,

```{r}
cat("print('# Header')")
```

will be rendered to markdown as the following: (note that the indentation here means this is code according to markdown syntax):

    ## # print('# Header')

Whereas, if results = 'asis' is used you will get the markdown

print('# Header')

The crucial thing to realise is that, although "print('# Header')" is valid R code, it only appears at stage 2 in the process, which is after all R code has been run.

The take-home message

Unfortunately, you can't expect results='asis' to output R code and then run it, as knitr has already finished running your R code by this point.

like image 141
wurli Avatar answered Jan 16 '23 00:01

wurli