8
votes

I want to include the code from a specific chunk of a one markdown document into a second markdown doc. I want to do it by referring to the chunk by name (no hacky references to line-numbers, please). I don't want to run all the code in the child because some of it is rather time-consuming.

Here's what I've tried. We have read_chunk for including plain R script in markdown docs. There is run_chunk but it's not clear if this can be used with external docs (I haven't had any luck so far).

And we can do this to get an entire markdown doc to run inside another one:

```{r child='first.Rmd'}
```

But how can I get just one specific chunk from a child document into another doc? Here's a small example:

This is test-main.Rmd

```{r pick-up-the-kid, child='test-child.Rmd'}
```

And this is test-child.Rmd

Hi, there. I'm a child.

```{r test-child-1}
1+1
dnorm(0)
```

```{r test-child-2}
2+2
dnorm(0)
```

When we run test-main.Rmd we get this:

Hi, there. I’m a child.

1+1
## [1] 2
dnorm(0)
## [1] 0.3989
2+2
## [1] 4
dnorm(0)
## [1] 0.3989

One method that almost does it is ref.label. If we edit test-main.Rmd like so:

```{r pick-up-the-kid, child='test-child.Rmd', ref.label='test-child-2'}
```

The output has the only the desired chunk, but it's duplicated, which is no good:

Hi, there. I’m a child.

2+2
## [1] 4
dnorm(0)
## [1] 0.3989
2+2
## [1] 4
dnorm(0)
## [1] 0.3989

One solution to the duplication is to use eval = FALSE, echo = FALSE in the chunk options in the child document:

```{r test-child-2, eval = FALSE, echo = FALSE}
2+2
dnorm(0)
```

which gives the desired result:

2+2
## [1] 4
dnorm(0)

But this is not convenient to alter the chunk in the child document, since that chunk is needed by other chunks in the child doc, and I don't want to change with a few chunks in the child doc each time I run the main doc, it's not good for reproducibility.

How can I get only chunk test-child-2 from test-child.Rmd into test-main.Rmd by reference to the chunk name (and without duplicates or fiddling with the chunk options)?

I'm looking for a function that could be calledchild_chunk where I can give the child doc name and chunk name and apply chunk options to it in the main doc that are independent of the chunk options in the child doc.

Or is the only solution to move code into R script files and share them between the two markdown docs?

2
Related to this, I made a function source_rmd_chunks() that sources chunks from an RMD file based on the chunk label name(s), link: gist.github.com/brshallo/e963b9dca5e4e1ab12ec6348b135362eBryan Shalloway

2 Answers

5
votes

I would try purl-ing the original child document and then reading the chunk in from the code tangle file, which you can then subsequently delete.

Here's test-main.Rmd

```{r echo=FALSE}
invisible(purl("test-child.Rmd", output="temp", quiet=TRUE))
read_chunk("temp")
```

```{r ref.label='test_child_2'}
```

```{r echo=FALSE}
unlink("temp")
```

I modified your test-child.Rmd to use different labels because yours weren't working on my machine:

Hi, there. I'm a child.

```{r test_child_1}
1+1
dnorm(0)
```

```{r test_child_2}
2+2
dnorm(0)
```

The output of knit('test-main.Rmd') is thus:

```r
2+2
```


```
## [1] 4
```

```r
dnorm(0)
```

```
## [1] 0.3989
```
0
votes

In 2021, you can use

```{r, include=F, cache=F}
knitr::read_chunk("my_file.Rmd")
```

```{r my_reusable_chunk}```
```

Where the chunk of interested in the file myfile.Rmd contains a line prefixed with ## ----:

## ---- my_reusable_chunk

Source: https://bookdown.org/yihui/rmarkdown-cookbook/read-chunk.html

This does not quite meet the requirement of the original question that the chunk name should be used, but it does not require much more effort (just include the magic comment).

(I find it hard to debug included chunks though...)