10

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!

ℕʘʘḆḽḘ
  • 18,566
  • 34
  • 128
  • 235

3 Answers3

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.

Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
  • pretty cool. essentially i can add to markdown any kind of crazy latex command as long as i import the packages – ℕʘʘḆḽḘ Sep 25 '18 at 10:49
  • it would be nice that `include_graphics` includes a `page_num` argument so that we can choose which page to show – ℕʘʘḆḽḘ Sep 25 '18 at 12:16
  • 1
    @ℕʘʘḆḽḘ Including raw LateX is possible due to pandoc's [raw_tex](https://pandoc.org/MANUAL.html#extension-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. – Ralf Stubner Sep 25 '18 at 12:23
  • 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! – ℕʘʘḆḽḘ Sep 25 '18 at 12:25
  • 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? – ℕʘʘḆḽḘ Sep 25 '18 at 12:40
  • 1
    No idea, but you are the third person reporting this, c.f. https://stackoverflow.com/questions/52480647/embed-a-pdf-in-a-r-markdown-file-and-adapt-pagination and https://stackoverflow.com/questions/52198354/size-of-the-embeded-pdf-document-in-rmarkdown – Ralf Stubner Sep 25 '18 at 12:43
  • one more reason to have this `num_page` arg in `include_graphics`... :) – ℕʘʘḆḽḘ Sep 25 '18 at 12:45
  • It includes only white pages. Could you provide an minimal working example with the distracting R code? – user3072843 Apr 24 '20 at 07:58
  • @user3072843 What includes only white pages? What example are you missing? – Ralf Stubner Apr 24 '20 at 08:14
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.

csgroen
  • 2,511
  • 11
  • 28
  • 1
    Yes, it can be problematic... particularly on Ubuntu Bionic (18.04). Ralf's suggestion seems to be a possible solution, using pdflatex. – csgroen Sep 24 '18 at 21:08
1

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")
```
cderv
  • 6,272
  • 1
  • 21
  • 31