10

Given a list of child documents, how can you choose which to insert into a master document based on some criteria?

In my use case, I am matching the unknown entries in one dataset to the desired entries in a second dataset. The second dataset has child documents associated with each entry. If a match is found, I want to include its associated child document.

In its most basic form, this psuedo-code shows the gist of what I am trying to achieve (inspired by this question here):

```{r, eval=TRUE}
child_docs <- setNames(c(TRUE, FALSE, TRUE, FALSE),
                       c("doc1.Rmd", "doc2.Rmd","doc3.Rmd","doc4.Rmd"))

for(i in seq_along(child_docs)){
    file <- names(child_docs)[i]
    eval_status <- child_docs[i]

    ```{r child = file, eval = eval_status}
    ```

}

```

Or, more simply:

```{r}
child_docs <- c("child/doc1.Rmd", "child/doc2.Rmd","child/doc3.Rmd","child/doc4.Rmd")
```

```{r child = child_docs}
```

I have also tried these, but they did not work (RMarkdown code chunk):

```{r}
child_docs <- c("child/doc1.Rmd", "child/doc2.Rmd","child/doc3.Rmd","child/doc4.Rmd")

for(i in seq_along(child_docs)){
    doc <- child_docs[i]
    knit_child(doc)
}

```

(Directly within the RMarkdown document):

`for(i in seq_along(child_doc)){ doc <- child_doc[i]; knit_child(doc)}`

For reference, the manual for doing this (in LaTeX) is here.

Community
  • 1
  • 1
user5359531
  • 3,217
  • 6
  • 30
  • 55

2 Answers2

15

Found the solution myself; simply pass a vector of child documents to the code chunk.

```{r}
child_docs <- c("doc1.Rmd", "doc2.Rmd","doc3.Rmd","doc4.Rmd")
```

```{r, child = child_docs}
```

After implementing my own code in order to obtain the list of child docs to include.

user5359531
  • 3,217
  • 6
  • 30
  • 55
  • Hello, out of curiosity, if you load all the libraries you need at ```doc1.Rmd```, given as in your example, do you need to load the libraries again at all the other libraries? – Jxson99 May 01 '20 at 21:25
  • 1
    @MasonBeau I do not believe so, However I would not advise that approach. If you are going to do this, you should instead be loading them into the parent document, e.g. the Rmd that is loading `doc1.Rmd`, etc. You should be careful if you do this since it makes your code more confusing if the child docs are calling functions and libraries they did not load. If you want a more modular and consistent codebase you should still call each library you intend to use inside each child doc. – user5359531 May 05 '20 at 10:33
  • That does seem like the simpler route, but I thought it'd be too redundant and that there might exist a more clever way to do so. Glad to know I was so off. TY. – Jxson99 May 06 '20 at 19:27
  • 1
    @MasonBeau I think you would be interested in this question here, which adresses these kinds of things in the R environment when knitting child documents; https://stackoverflow.com/questions/34498734/how-do-you-hide-and-pass-variables-in-knitr-child-documents – user5359531 May 18 '20 at 12:54
6

You can dynamically render a child document

```{r, result='asis'}
cat(knitr::knit_child("child.Rmd", quiet=TRUE))
```

which gives you great flexibility.

The "trick" is the result='asis' so that the output is then passed on for conversion (as opposed to "knitting").

Alternatively, you can tag the object and avoid the "asis" in the chunk options:

```{r}
cat(knitr::asis_output(knitr::knit_child("child.Rmd", quiet=TRUE)))
```

This is more robust, as it allows you to use this in nested functions, etc., and not have to rely on the caller having set the "correct" chunk options.

If you want to pass in "current" variables and libraries, pass in the current environment too:

```{r, result='asis'}
cat(knitr::knit_child("child.Rmd", quiet=TRUE, envir=environment()))
```
dsz
  • 4,542
  • 39
  • 35