how to add a (multipage) pdf to rmarkdown?
Asked Answered
C

3

11

Consider this simple example

library(dplyr)
library(ggplot2)
library(tidyr)

mydata <- data_frame(group = c('a', 'a', 'a', 'b', 'b', 'b'),
                     x = c(1,2,3,5,6,7),
                     y = c(3,5,6,4,3,2))

mydata2 <- mydata %>% group_by(group) %>% 
  nest() %>% 
  mutate(myplot = map(data, ~ggplot(data = .x, aes(x = x, y = x)) + geom_point()))

pdf("P://mychart.pdf")
print(mydata2$myplot)
dev.off()

The code above will output a pdf with two pages. How can I show these two pages on my rmarkdown document?

Using

---
title: "crazy test"
output:
  pdf_document
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.pos = 'h')
```


ttt

## this is a test!!

```{r label, out.width = "85%", fig.cap = "caption"}
knitr::include_graphics(path = "P://mychart.pdf")
```

will only show the first page of the pdf! Where is the other chart? :(

enter image description here

Any ideas?

Thanks!

Cerebrate answered 24/9, 2018 at 19:45 Comment(8)
Could you make one pdf for each graph (numbered) and then add them to the markdown document through a loop?Formula
no but assume you get the pdf from outside. you only have the pdf. how would you do it?Kearney
I can't reproduce your example (what package does nest come from?). The include_graphics function doesn't seem to support multipage pdfs as is. Try splitting your pdf with staplr (possibly in a chunk with echo=FALSE) and then including the resulting graphs in a include_graphics loop.Formula
hold on let me add the packages. sorry about thatKearney
can you run it now? do you mind posting your solution with staplr? sounds really promising!!! thanksKearney
You could use the LaTeX package pdfpages, c.f. https://mcmap.net/q/1015671/-embed-a-pdf-in-a-r-markdown-file-and-adapt-pagination.Hermosa
hi Ralf! I see but how could i make it work in a rmarkdown chunk?!Kearney
@RalfStubner that works! you do mind posting your solution? its pretty neat in the context of rmarkdownKearney
H
13

One can use pdfpages to include multiple pages from a PDF file at once. However, these are included on separate pages. While it is possible to add page numbers, you cannot easily put these images into a figure environment. Fortunately, \includegraphics has an option to use individual pages from a PDF. Unfortunately, knitr::include_graphics does not allow passing additional arguments to \includegraphics.

Here both possibilities:

---
title: "crazy test"
output:
  pdf_document
header-includes:
  - \usepackage{pdfpages}
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.pos = 'h')
```


```{r, include=FALSE}
library(dplyr)
library(ggplot2)
library(tidyr)
library(purrr)

mydata <- data_frame(group = c('a', 'a', 'a', 'b', 'b', 'b'),
                     x = c(1,2,3,5,6,7),
                     y = c(3,5,6,4,3,2))

mydata2 <- mydata %>% group_by(group) %>% 
  nest() %>% 
  mutate(myplot = map(data, ~ggplot(data = .x, aes(x = x, y = x)) + geom_point()))

pdf("mychart.pdf")
print(mydata2$myplot)
dev.off()
```


## this is a test!!

Only first page

```{r label, out.width = "85%", fig.cap = "caption"}
knitr::include_graphics(path = "mychart.pdf")
```

All pages but w/o caption and taking a full page

\includepdf[pages=-,nup=2,pagecommand={}]{mychart.pdf}

Alternative, using explicit LaTeX commands.

\begin{figure}
\includegraphics[page=1,width=0.5\linewidth]{mychart.pdf}
\includegraphics[page=2,width=0.5\linewidth]{mychart.pdf}
\caption{\label{fig:test} Test.}
\end{figure}

One could also put these into a R chunk with cat() and result = 'asis'. However, the options for setting caption etc. are still not used.

Hermosa answered 25/9, 2018 at 9:2 Comment(9)
pretty cool. essentially i can add to markdown any kind of crazy latex command as long as i import the packagesKearney
it would be nice that include_graphics includes a page_num argument so that we can choose which page to showKearney
@Cerebrate Including raw LateX is possible due to pandoc's raw_tex extension. Adding a specific option for individual pages in a PDF would be strange, since it would not make sense in many use cases of the command. However, a more generic "pass these additional arguments" might be worthwhile.Hermosa
hello i actually disagreee. In many cases one only wants to add a given table in a paper, or part of the appendix, or a single chart. In that case, including just the page wanted in necessary. Otherwise one has to manually extract the page with acrobat, and then use the command. which is really cumbersome if you have many pdfs... :) thanks again!Kearney
on a side note, using \includepdf[pages=1,pagecommand={},scale = 0.9] shows my chart in the pdf, but the chart is SO SMALL I can barely see it :) any ideas what is the issue?Kearney
No idea, but you are the third person reporting this, c.f. #52481147 and #52198854Hermosa
one more reason to have this num_page arg in include_graphics... :)Kearney
It includes only white pages. Could you provide an minimal working example with the distracting R code?Rotenone
@Rotenone What includes only white pages? What example are you missing?Hermosa
F
4

Here's the Rmd solution with staplr. Please be advised that you need to install pdftk for split_pdf to work

---
title: "crazy test"
output:
  pdf_document
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.pos = 'h')
```

## Split pdf

```{r}
staplr::split_pdf("mychart.pdf", output_directory = ".", prefix = "mychart_")
```

## Add pdfs

```{r label, out.width = "85%", fig.cap = c("caption 1", "caption 2"), echo = FALSE}
flist <- list.files()
mychart_files <- flist[grep("mychart_", flist)]
knitr::include_graphics(mychart_files)
```

Also, include graphics doesn't work in a loop. But it accepts multiple paths, so that works out well.

Formula answered 24/9, 2018 at 20:51 Comment(1)
Yes, it can be problematic... particularly on Ubuntu Bionic (18.04). Ralf's suggestion seems to be a possible solution, using pdflatex.Formula
A
2

knitr has a specific chunk option called out.extra that allows to pass options to the \includegraphics command. See about this option in knitr doc.

This means it can be used to page the option page. Using the example above, you could do

---
title: "crazy test"
output:
  pdf_document:
    keep_tex: TRUE
---

```{r global_options, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, fig.pos = 'h')
```


```{r, include=FALSE}
library(dplyr)
library(ggplot2)
library(tidyr)
library(purrr)

mydata <- tibble(group = c('a', 'a', 'a', 'b', 'b', 'b'),
                     x = c(1,2,3,5,6,7),
                     y = c(3,5,6,4,3,2))

mydata2 <- mydata %>% group_by(group) %>% 
  nest() %>% 
  mutate(myplot = map(data, ~ggplot(data = .x, aes(x = x, y = x)) + geom_point()))

pdf("mychart.pdf")
print(mydata2$myplot)
dev.off()
```

Only first page

```{r label, out.width = "85%", fig.cap = "caption"}
knitr::include_graphics(path = "mychart.pdf")
```

second page

```{r label2, out.width = "85%", fig.cap = "caption", out.extra="page=2"}
knitr::include_graphics(path = "mychart.pdf")
```
Acrobatics answered 28/1, 2021 at 15:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.