1

I'm producing a solutions manual for a book, using .Rmd files with the following YAML header:

---
title: "DDAR: Solutions and Hints for Exercises"
date: "`r Sys.Date()`"
output: 
  word_document:
    reference_docx: solutions-setup.docx
---

where I control the general layout of the document with the reference_docx to get an output Word document.

There will be many figures, and I'd like to set some global graphics parameters to give relatively tight bounding boxes and reasonable font sizes in the figures without having to tweak each one from what I see in a PDF document.

I tried the following, but the par() setting doesn't seem to have any effect:

{r setup, echo=FALSE} options(digits=4) par(mar=c(5,4,1,1)+.1)

Instead I get images like the following in my document with larger bounding boxes than I would like and with much larger font sizes than I would like.

sample image

I know how to control all this in .Rnw files produced with LaTeX, but I can't find how to do it in .Rmd -> Word. Is there a chunk hook I could use? I don't think that there is an out.width chunk option that re-scales a figure as in LaTeX.

user101089
  • 3,756
  • 1
  • 26
  • 53
  • 1
    The `par` `mar`gins you've used are the default R margins, which are about the size of what your image shows. What happens if you make them much smaller? – thelatemail Jan 11 '16 at 01:29

2 Answers2

4

@scoa's answer shows how to use a hook to set some graphical parameters at the beginning of each chunk. This is necessary because "by default, knitr opens a new graphics device to record plots and close it after evaluating the code, so par() settings will be discarded", i.e. graphical parameters for later chunks cannot be set in an early setup-chunk but need to be set for each chunk separately.

If this behavior is not wanted, the package option global.par = TRUE can be used:

opts_knit$set(global.par = TRUE)

Finding the correct values for the margins is sometimes quite painful. In these cases, hook_pdfcrop can help. In all chunks where the option crop = TRUE, white margins will be removed. To apply this to all chunks, use

library(knitr)
knit_hooks$set(crop = hook_pdfcrop)
opts_chunk$set(crop = TRUE)

This works for docx output as well because "when the plot format is not PDF (e.g. PNG), the program convert in ImageMagick is used to trim the white margins" (from ?hook_pdfcrop).

Note that under some circumstances, cropping plots has the side effect of sometimes apparently different "zoom" factors of plots: This happens in cases where we start with identical sized elements on two plots but larger white margins around one of the plots. If then both are resized to a fixed output width after cropping, elements on the plot with larger margins look larger. However, this is not relevant for docx output because out.width/out.height cannot be used in that case.

CL.
  • 14,577
  • 5
  • 46
  • 73
  • `opts_knit$set(global.par = TRUE)` is the correct way to make knitr respect global `par()` options. I know about `pdfcrop`, but that doesn't work for MS Word `.docx` output, where the images are all generated in PNG format. – user101089 Jan 11 '16 at 19:51
  • Ah, l forgot about the docx context. Regarding your first sentence: yes. That's exactly what I wrote, didn't I? – CL. Jan 11 '16 at 19:53
  • Update: `hook_pdfcrop` works with `.docx` and `png` images, too. See `? hook_pdfcrop`: "when the plot format is not PDF (e.g. PNG), the program convert in ImageMagick is used to trim the white margins". – CL. Jan 12 '16 at 08:21
2

The knitr documentation for hooks actually uses small margins as an example of what you can do with hooks. Here is a solution (adapted from this documentation).

---
output: word_document
---

```{r setup, echo=FALSE}
library(knitr)
knit_hooks$set(small.mar = function(before, options, envir) {
    if (before)    par(mar=c(5,4,1,1)+.1)  # smaller margin on top and right
})
opts_chunk$set(small.mar=TRUE)
```

```{r}
plot(iris$Sepal.Length)
```

Using opts_chunk$set(small.mar=TRUE) is a way to avoid passing it to every chunk in the document.

The margin appears fixed (screenshot from the docx output in libreoffice with default reference-docx).

enter image description here

scoa
  • 19,359
  • 5
  • 65
  • 80
  • 1
    Upvoted, but two things you might want to add: [global.par](http://yihui.name/knitr/options/) to make `par()` settings from the current chunk to be preserved and [hook_pdfcrop](https://github.com/yihui/knitr-examples/blob/master/085-pdfcrop.Rnw) to avoid some of the hassle with margins. – CL. Jan 11 '16 at 15:50
  • @CL. you should make that an answer, it is better than mine. – scoa Jan 11 '16 at 19:04
  • Done. I think together our answers give a quite comprehensive picture. – CL. Jan 11 '16 at 19:34