Child documents

Input child files into the main document

2012-01-18

It can sometimes be convenient to separate a large document in several smaller documents that are reunited as necessary at compilation time in a main document. Like the command \SweaveInput{} in Sweave, knitr also has the similar functionality, which enables us to insert child documents into a main document. The idea is like the command \input{} or \include{} in LaTeX to manage a large document in smaller parts. There are two approaches to input child documents in a main document. We can also compile an incomplete child document as a complete LaTeX document when we specify its parent with set_parent().

Note knitr accepts child documents in the Markdown format, as well as in the LaTeX/Sweave format and other formats.

Using chunk option child for Markdown (.Rmd) documents

The chunk option child supports the inclusion of child documents. For example here is how to combine a main document with a child document. We create a child document named knitr-child.Rmd:

# Details from the child document

Hi, there. I'm a child with a plot and as many details as necessary.

```{r test-child}
plot(trees)
```

and we create a main document named main.Rmd

---
title: "Main report"
output: html_document
---
# Summary 

```{r test-main, child = 'knitr-child.Rmd'}
```

# Conclusion

Compiling main.Rmd generates HTML output for both documents. The content of the child document is located in the middle of the main document, inserted at the placeholder defined by ```{r test-main, child = 'knitr-child.Rmd'}.

Using chunk option child for Latex (.Rnw) documents

The chunk option child supports the inclusion of child documents. For example, we have a main document named knitr-input.Rnw here:

\documentclass{article}
\begin{document}

<<test-main>>=
options(width = 60)
summary(iris)
@

Let's see how to work with child documents in knitr. Below we input
the file \textsf{knitr-input-child.Rnw}:

<<child-demo, child='knitr-input-child.Rnw'>>=
@

Done!

\end{document}

We want to include a child document knitr-input-child.Rnw in it:

This chunk below is from the child document.

<<test-child, out.width='2in'>>=
1+1
rnorm(5)
plot(1)
boxplot(1:10)
str(mtcars)
@

You then can compile the main document with:

library(knitr)
knit('knitr-input.Rnw')
## child document will be compiled too

You can freely nest one Rnw document in the other, as long as the nested structure is clear in your mind.

Using knit_child() with inline R code

Sweave searches for \SweaveInput{} in the main document, and weaves the child documents, whereas knitr does not search for such character strings, instead, you can directly use \Sexpr{} with the function knit_child() to input a child document.

The above example can be equivalently done with:

\Sexpr{knit_child('knitr-input-child.Rnw')}

The function knit_child() is just a wrapper to knit() and returns the compiled content as a character string to be inserted into the main output document.

Be sure to read ?knit_child to know more about the control of evaluation (argument eval), which is similar to what was described above in the first approach.

Comments on \SweaveInput{}

It is strongly discouraged to use \SweaveInput{}, and this command has been deprecated since knitr v1.0. Originally I did not plan to support \SweaveInput{} (but I did it later anyway in #39), and here were my reasons:

  1. I want to keep the number of new LaTeX commands minimal; if \Sexpr{} does the job, I do not want to use another \SweaveInput{} (I expressed my opinion on why I do not like these pseudo-LaTeX commands in the end of the demo page of minimal examples);
  2. I tend to think <<>>= holds meta information about the literate programming document, and <<child='foo-bar.Rnw'>>= is one piece of the meta information telling knitr that for this chunk, please compile and input a child document here; it is essentially not a LaTeX command, so I do not want a command \FooBarInput{} which looks like \input{};
  3. The implementation in knitr is more flexible than \SweaveInput{} because it supports conditional evaluation as well; you can use knit_child('foo-bar.Rnw', eval=dothis) or <<child='foo-bar.Rnw', eval=dothis>>= where the global variable dothis is a logical variable which controls if this expression or chunk should be evaluated; if dothis == FALSE, you have essentially commented out the child document; meanwhile, it is also possible to input multiple child documents in a chunk like <<child=c('foo1.Rnw', 'foo2.Rnw', 'foo3.Rnw')>>=; you can easily group a set of child documents together to form a report in this way;
  4. It brings me additional difficulty to parse \SweaveInput{} from the source document (\SweaveOpts{} has the same trouble);

You may use this a piece of R code for the transition from Sweave to knitr:

kids = list.files(pattern = '\\.Rnw$')
sprintf("<<child%s, child='%s'>>=", 1:length(kids), kids)
## copy the results to save some typing efforts

Knit child documents in a standalone mode

Child documents are often incomplete – the missing part is the LaTeX preamble as well as \begin{document} and \end{document}. Sometimes we may want to compile such child documents as if they were complete LaTeX documents. The only one thing we need to do is to extract an appropriate preamble from a parent document and add it to this child document. The function set_parent() enables this feature; we can use it either in \Sexpr{} or a code chunk in the child document, e.g.

\Sexpr{set_parent('main-document.Rnw')}

or

<<set-parent, echo=FALSE, cache=FALSE>>=
set_parent('main-document.Rnw')
@

Then the child document will behave as if it had a preamble – the output LaTeX document will have a preamble, and the tikz graphics in this document will be affected by the preamble as well.