Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Images pushed off slides in beamer output from R markdown

I'm using R markdown v2 to create a beamer presentation. Most of my slides contain an image generated by ggplot, sometimes with explanatory text above that slide. I've found that I really have to individually tweak the size of each element (i.e. image, text, etc) on each slide to ensure that the image doesn't get pushed off the end of the slide.

This ends up getting very time consuming, and kind of defeats one of the stated purposes of R markdown: that is, being a quick way to spit out reproducible research.

I was wondering if there are any ways to have the various elements intelligently auto-size? Even if it doesn't look great, at least things wouldn't get pushed off the end? Or if not, perhaps there are other methods people use to make sure things just fit that don't take too much time.

Thanks in advance for your thoughts...

like image 380
Alexander Shenkin Avatar asked Feb 02 '15 18:02

Alexander Shenkin


1 Answers

This is a tricky problem because typesetting is tricky. Rmarkdown does a good job at hiding a lot of thorny details, but if you want to typeset, you need to typeset. It's even hard in Latex, as you'll see. There are so many moving parts, e.g. caption and legends, rendering an image which is then included in an intermediate .tex file so pandoc can make your .pdf. A fully generalizable solution is not possible without demanding a lot of input (which is what you are trying to avoid in the first place).

I don't think creating Beamer presentations in itself is incompatible with reproducible research, but is a legitimate output, likely along with other reports.

But before launching into the Latex, you should consider the very simple workaround of only putting a graphic and no text on each slide. This reliably fits the image on the slide. You can then use annotations in ggplot2 to add additional text. This is what I would do.

The following Rmarkdown uses a complicated bit of embedded Latex to do more-or-less what you want. It does limit the image to the bottom half of the screen (but this can be changed if you learn more about tikz...), but does scale the image to the remaining page size as the upper text block increases. It does also, of course, scale all your legends, but you can potentially tweak these in ggplot2.

---
title: "Some beamer slides with figures"
author: Somebody
date: November 06, 2015
output:
  beamer_presentation:
    keep_tex: yes
header-includes:
- \usepackage{graphicx}
- \usepackage{tikzpagenodes}
- \usetikzlibrary{calc}
- \usepackage{caption}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, fig.path="figures/beamer-example/")

library(ggplot2)
```

```{r}
mtcars$gear <- factor(mtcars$gear,levels=c(3,4,5),
   labels=c("3gears","4gears","5gears"))
mtcars$am <- factor(mtcars$am,levels=c(0,1),
   labels=c("Automatic","Manual"))
mtcars$cyl <- factor(mtcars$cyl,levels=c(4,6,8),
   labels=c("4cyl","6cyl","8cyl"))
```
## A default plot

```{r mpg-plot}
qplot(mpg, data=mtcars, geom="density", fill=gear, alpha=I(.5),
   main="Distribution of Gas Milage", xlab="Miles Per Gallon",
   ylab="Density")
```

## test

  - some text which
  - fills vertical 
  - space

\begin{tikzpicture}[overlay,remember picture]
    % Caption
    \node [anchor=south west,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (current page text area.south west) {%
    };
    % Image
    \path let \p0 = (0,0), \p1 = (caption.north) in
        node [inner sep=0pt,outer sep=0pt,anchor=south] at (\x1,\y1) {%
            \pgfmathsetmacro\imgheight{\y0-\y1-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{figures/beamer-example/mpg-plot-1}%
    };
\end{tikzpicture}

## test2

  - some text which
  - fills vertical 
  - space
  - but squashes
  - the image badly

\begin{tikzpicture}[overlay,remember picture]
    % Caption
    \node [anchor=south west,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (current page text area.south west) {%
    };
    % Image
    \path let \p0 = (0,0), \p1 = (caption.north) in
        node [inner sep=0pt,outer sep=0pt,anchor=south] at (\x1,\y1) {%
            \pgfmathsetmacro\imgheight{\y0-\y1-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{figures/beamer-example/mpg-plot-1}%
    };
\end{tikzpicture}

## test3
\begin{tikzpicture}[overlay,remember picture]
    % Caption
    \node [anchor=south west,outer sep=0pt,inner sep=0pt,text width=\textwidth] (caption) at (current page text area.south west) {%
    };
    % Image
    \path let \p0 = (0,0), \p1 = (caption.north) in
        node [inner sep=0pt,outer sep=0pt,anchor=south] at (\x1,\y1) {%
            \pgfmathsetmacro\imgheight{\y0-\y1-\abovecaptionskip}%
            \includegraphics[height=\imgheight pt,width=\textwidth,keepaspectratio]{figures/beamer-example/mpg-plot-1}%
    };
\end{tikzpicture}

You can read some gory details in: https://tex.stackexchange.com/questions/14512/how-to-define-a-figure-size-so-that-it-consumes-the-rest-of-a-page

like image 108
Jack Wasey Avatar answered Oct 12 '22 14:10

Jack Wasey