How to combine two RMarkdown (.Rmd) files into a single output?

RKnitrPandocR Markdown

R Problem Overview


I have two files in the same folder: chapter1.Rmd and chapter2.Rmd, with the following content:

chapter1.Rmd

---
title: "Chapter 1"
output: pdf_document
---

## This is chapter 1. {#Chapter1}

Next up: [chapter 2](#Chapter2)

chapter2.Rmd

---
title: "Chapter 2"
output: pdf_document
---

## This is chapter 2. {#Chapter2}

Previously: [chapter 1](#Chapter1)

How can I knit these so that they combine into a single pdf output?

Of course, render(input = "chapter1.Rmd", output_format = "pdf_document") works perfectly but render(input = "chapter1.Rmd", input = "chapter2.Rmd", output_format = "pdf_document") does not.

Why do I want to do this? To break up a giant document into logical files.

I've used @hadley 's bookdown package to build latex from .Rmd but this seems like overkill for this particular task. Is there a simple solution using knitr/pandoc/linux command line I'm missing? Thanks.

R Solutions


Solution 1 - R

> August, 2018 update: This answer was written before the advent of bookdown, which is a more powerful approach to writing Rmarkdown based books. Check out the minimal bookdown example in @Mikey-Harper's answer!

When I want to break a large report into separate Rmd, I usually create a parent Rmd and include the chapters as children. This approach is easy for new users to understand, and if you include a table of contents (toc), it is easy to navigate between chapters.

report.Rmd

---  
title: My Report  
output: 
  pdf_document:
    toc: yes 
---

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

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

chapter1.Rmd

# Chapter 1

This is chapter 1.

```{r}
1
```

chapter2.Rmd

# Chapter 2

This is chapter 2.

```{r}
2
```

Build

rmarkdown::render('report.Rmd')

Which produces: My report

And if you want a quick way to create the chunks for your child documents:

rmd <- list.files(pattern = '*.Rmd', recursive = T)
chunks <- paste0("```{r child = '", rmd, "'}\n```\n")
cat(chunks, sep = '\n')
# ```{r child = 'chapter1.Rmd'}
# ```
#
# ```{r child = 'chapter2.Rmd'}
# ```

Solution 2 - R

I'd recommend that people use the bookdown package for creating reports from multiple R Markdown files. It adds a lot of useful features like cross-referencing which are very useful for longer documents.

Adapting the example from @Eric, here is a minimal example of the bookdown setup. The main detail is that the main file has to be called index.Rmd , and must include the additional YAML line site: bookdown::bookdown_site:

index.Rmd

---
title: "A Minimal bookdown document"
site: bookdown::bookdown_site
output:
  bookdown::pdf_document2:
    toc: yes
---

01-intro.Rmd:

# Chapter 1

This is chapter 1.

```{r}
1
```

02-intro.Rmd:

# Chapter 2

This is chapter 2.

```{r}
2
```

If we Knit the index.Rmd bookdown will merge all the files in the same directory in alphabetical order (this behaviour can be changed using an extra _bookdown.yml file).

enter image description here

Once you get comfortable with this basic setup, it is easy to customise the bookdown document and output formats using additional configuration files i.e. _bookdown.yml and _output.yml

> Further Reading > > - R Markdown: The definitive Guide: Chapter 11 provides a great overview of bookdown > - Authoring books with bookdown provides a comprehensive guide on bookdown, and recommended for more advanced details.

Solution 3 - R

This worked for me:

Rmd_bind <- 
    function(dir = ".",
    book_header = readLines(textConnection("---\ntitle: 'Title'\n---")))
{
    old <- setwd(dir)
    if(length(grep("book.Rmd", list.files())) > 0){
    warning("book.Rmd already exists")
    }
    write(book_header, file = "book.Rmd", )
    cfiles <- list.files(pattern = "*.Rmd", )
    ttext <- NULL
    for(i in 1:length(cfiles)){
    text <- readLines(cfiles[i])
    hspan <- grep("---", text)
    text <- text[-c(hspan[1]:hspan[2])]
    write(text, sep = "\n", file = "book.Rmd", append = T)
    }
    render("book.Rmd", output_format = "pdf_document")
    setwd(old)
    }

Imagine there's a better solution and would be nice to have something like this in rmarkdown or knitr packages.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRobinLovelaceView Question on Stackoverflow
Solution 1 - REricView Answer on Stackoverflow
Solution 2 - RMichael HarperView Answer on Stackoverflow
Solution 3 - RRobinLovelaceView Answer on Stackoverflow