How to write R script into Rmd as functioning code chunk?

Hi,

I'd like to take an R script and write it into an Rmarkdown document as a functioning code chunk.

For example, my .R file is called analysis.R and contains some R code such as

plot(rnorm(100))

My template Rmarkdown document is as follows:

---
title: "Insert R as Code Chunk"
output: html_document
---

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

#Here's where I pipe in the analysis.R script as a functioning code chunk

The output .Rmd I'm looking for is simply:

---
title: "Insert R as Code Chunk"
output: html_document
---

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


```{r}
plot(rnorm(100))
```
1 Like

Here's how I did it:

I first added some hooks in the Rmd document where I wanted to drop the script:

---
title: "Insert R as Code Chunk"
output: html_document
---

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

{{AnalysisStart}}

{{AnalysisEnd}}

I then wrote a function that reads in my script and does a find and replace for the hooks within the .Rmd file

write_to_rmd <- function(script, rmd, hook, output_path){
  
  #Read in script
  source <-  readr::read_file(script)

  #Concatenate Rmd chunk yml
  source <- paste0("```{r, eval = F}\n",source, "```")
  
  #Read in Rmd
  rmd <- readr::read_file(rmd)
  
  #Get mustache regex in chapter .Rmd files
  header_regex <- sprintf("\\{\\{%sStart\\}\\}(.*?)\\{\\{%sEnd\\}\\}", 
                          hook, 
                          hook)
  
  #Do a gsub to replace hooks with script text
  output <- gsub(header_regex, source, rmd)
  
  #write output to file
  readr::write_file(output, path = output_path)

}

The function output (written to output_path) looks like

---
title: "Insert R as Code Chunk"
output: html_document
---

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


```{r}
plot(rnorm(100))
```
1 Like

You may be interested in the knitr function knit_child(). It can be used to insert R scripts as if they were code chunks in an R Markdown file.

To demonstrate, I created an R script called analysis.R that contained:

plot(rnorm(100))

And a template R Markdown file that contained:

---
title: "Insert R as Code Chunk"
output: html_document
---

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

`r knitr::spin_child("analysis.R")`

When I knit the file to HTML, the code in the R script appears as if it was a chunk in the R Markdown file:

8 Likes

This is a great function, thanks for sharing!

1 Like

I think what you are looking for is exactly what the code chunk option can do

---
title: "Insert R as Code Chunk"
output: html_document
---

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


```{r, code = readLines("analysis.R")}
```

This will use the code inside the file as the code in the chunk. You can knit as any other document.

See Chunk option documentation

7 Likes

Hi

I have a similar issue. I want to write generic code inside a Rmarkdown document which generically creates (in my case for flexdashboard) rows and corresponding plots. Is something like this even possible?
It's also possible to write the plot into a tempfile and read it out in a chunk via the code-option. But then I can't write the row configuration since that has to be outside of the chunk.
Here a repex:

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: fill
params:
  format: "1x1"
---

```{r setup, include=FALSE}
library(flexdashboard)
library(stringr)
library(plotly)
library(rlang)
```

```{r config, include=FALSE}
nrows <- str_extract(params$format, "^[:digit:]+(?=x)") %>% as.numeric()
ncols <- str_extract(params$format, "(?<=x)[:digit:]+$") %>% as.numeric()
row_height <- 1000/nrows

make_row_sep <- function() {
  paste0("Row {data-height=", row_height, "}\n", paste0(rep("-", 70), collapse = ""), "\n\n")
}
make_row_graphs <- function(plot, title) {
  paste0("### Graph ", title, "\n```{r}\n", quo_name(plot), "\n```\n\n ", collapse = "")
}
p <- list(expr(plot_ly(economics, x = ~pop)))
```

```{r write file}
file <- c()
for (i in seq_len(nrows)) {
  file <- paste0(file, make_row_sep(), make_row_graphs(p[[i]], LETTERS[i]))
}
```

```{r output, results='asis'}
cat(file)
```

Thanks in advance!

Ok, I think I got a workaround:
I do all the formatting (make_row_sep and make_row_graphs) outside of the Rmd and just leave

---
title: "Untitled"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
    vertical_layout: fill
---

```{r setup, include=FALSE}
library(flexdashboard)
library(stringr)
library(plotly)
library(rlang)
```

in the Rmd-file. Then I copy this file to a temp-Rmd file and append the dynamic code to the new file by readr::write_lines(). I then call rmarkdown::render() on the appended file and done.

I would still be interested in a solution that works inside the Rmd itself, if someone knows how to do that :slight_smile:.