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.
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.
#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.
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).
Related
I'm trying to create a summary table with the package vtable. I do get a table but somehow the font size is super large and not the whole table is shown? I'm really at a loss here. I have spent hours on it, but could not find a solution... Can please someone tell me how to get a smaller table (font size and the whole table in a pdf document?
---
title: "Example"
date: "22 March 2021"
output:
pdf_document
---
{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(vegan)
library(vtable)
{r dune}
data(dune.env)
{r plot1, echo = F,results='asis',out.width='10%',message=F, fig.show='hold'}
st(dune.env,summ=c('mean(x)','median(x)','min(x)','max(x)'),group="Management",group.long = TRUE,out="latex")
By default, sumtable with out = 'latex' applies a LaTeX \resizebox{\textwidth} to the table to make it fit horizontally on the page. When the table is very narrow and tall, though, like this one, the resizebox can scale it to be bigger (making the text big).
You can control the width of the table with the fit.page option, which scales the horizontal width of the table. By default it's '\\textwidth', but you could do, for example, .6\\textwidth to only fill 60% of the horizontal space. This is what I get with fit.page='.5\\textwidth':
Now, this makes the text tiny, but it does fit. This is a consequence of LaTeX giving tall tables a hard time, and having no built-in support for multi-page tables. So it just fills up a page and the rest isn't shown. This is a LaTeX thing, not sumtable. There isn't currently support for multi-page LaTeX tables in sumtable/vtable. However, you could add keep_tex: true to your YAML, then after the fact go in and edit the TeX file to use the longtable LaTeX package, which adds support for multi-page tables, and turn the \begin{table} into \begin{longtable}, etc..
I am using RMarkdown to create a html file (my preferred format). I then use the officer package to create a powerpoint (PPT) (everyone else's preferred format) that reads in the .png images that are automatically created and saved when I knit the document (I believe this is default when the fig.path is specified).
To get consistent fontsize throughout the PPT figures, I have specified in each knitr chunk fig.width, out.width, etc to be equal to the relevant PPT placeholder dimensions. E.G if the PPT placeholder is 5.29in high x 5.89in wide, then in the knitr chunk I specify , out.height="5.29in", out.width="5.89in", fig.height=5.29, fig.width=5.89). This seems to work in terms of the PPT file, however it results in extremely small figures for the HTML file. Is there a way to get the knitr code to work for both html and PPT, without needing to specifically save the image, using, for example ggsave()?
Following is some auto-generated test code:
---
title: "Test_Figure_Size"
output:
html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(fig.path = "Delete_Me/", echo=FALSE)
```
When you include out.height, out.width the figure is extremely small in the knitted html document, but perfectly sized as a .png file.
```{r pressure, echo=FALSE, out.height="5.29in", out.width="5.89in", fig.height=5.29, fig.width=5.89}
plot(pressure)
```
When you say out.height="5.29in", out.width="5.89in", those values are written into the HTML output as height and width attributes of the img. But height and width are expressed in pixels, so you'll end up with a figure about 5 pixels square.
I don't use Powerpoint, but is there a way to specify the image size in pixels, e.g. "589px" or something similar? Then it will use the same scale as the browser, and things should be consistent.
I am trying to add a cover page which is already created in a PDF.
```{r echo=FALSE,out.width='8.27in',out.height='11.69in'}
knitr::include_graphics('CoverPage.pdf')
```
I want to change the margins of the first page only. Can you please help me with this?
The following was tried but it changes the margin of the whole document:
geometry: "left=3cm,right=3cm,top=2cm,bottom=2cm"
If you are fine with some bare LaTeX in your RMD file, then this can be easily achieved using the geometry package. Just define a newgeometry before the cover is included and restoregeometry afterwards (reads almost like English …).
---
output:
pdf_document
---
```{r, echo = FALSE, results = "asis"}
cat("\\newgeometry{left=3cm,right=3cm,top=2cm,bottom=2cm}")
knitr::include_graphics("CoverPage.pdf")
cat("\\restoregeometry")
```
\clearpage
Note the position of the page number. Restoring the margins was successful!
It is important to use the chunk option results="asis" and cat() to print raw LaTeX and to escape the backslashes with an additional backslash.
I created a custom function which sets mfrow to nxn and creates n^2 scatter plots, with multiple data sets on each plot, based on an input list of data frames. The signature of my plotting function looks like this:
plot.return.list<-function(df.list,num.plot,title)
Where df.list is my list of data frames, num.plot is the total number of plots to generate (used to set mfrow) and title is the overall plot title (the function generates titles for each individual sub-graph).
This creats plots fine when I run the function from the console. However, I'm trying to get this figure into a markdown document using RStudio, like so:
```{r, fig.height=6,fig.width=6}
plot.return.list(f.1.list,4,bquote(atop("Numerical Approximations vs Exact Soltuions for "
,dot(x)==-1*x*(t))))
```
Since I haven't set the echo option in my {r} statement, this prints both the plotting code as well as the plot itself. However, if my first line instead reads:
{r, fig.height=6,fig.width=6,echo=FALSE}
Then both the code AND the plot disappear from the final document.
How do I make the plot appear WITHOUT the code? According to the example RStudio gives, setting echo=FALSE should make the plot appear without the code, but that isn't the behavior I'm observing.
EDIT: I seem to have tracked my problem down to kable. Whether or not I'm making a custom plot-helper function, any call to kable kills my plot. This can be reproduced in a markdown:
---
title: "repro"
author: "Frank Moore-Clingenpeel"
date: "October 9, 2016"
output: pdf_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
options(default=TRUE)
repro.df<-data.frame((0.1*1:10)%*%t(1:10))
```
```{r, echo=FALSE}
kable(repro.df)
```
```{r, fig.height=6,fig.width=6,echo=FALSE}
plot(repro.df[,1],repro.df[,2])
```
In this code, the plot won't plot because I have echo set to false; removing the flag makes the plot visible
Also note that in my repro code, kable produces a table with a bunch of garbage in the last line--I don't know why, but this isn't true for my full original code, and I don't think it's related to my problem.
Thanks for the reproducible example. From this I can see that the problem is you don't have a newline between your table chunk and your plot chunk.
If you were to knit this and examine the MD file produced by knit (or set html_document as your output format and have keep_md: true to look at it), you would see that the table code and plot code are not separated by any newline. Pandoc needs this to delimit the end of the table. Without it, it thinks your ![](path/to/image.png) is part of the table and hence puts it as a "junk line" in the table rather than an image on its own.
Just add a newline between the two chunks and you will be fine. (Tables need to be surrounded with blank lines).
(I know you are compiling to LaTeX so it may confuse you why I am talking about markdown. In case it does, when you do Rmd -> PDF, Rmarkdown uses knit to go from RMD to MD, and then pandoc to go from MD to tex. This is why you still need to make sure your markdown looks OK).
I'm trying to build an automated report that will have three charts right underneath each other without margin space between each other.
I've mocked up my problem with the following Rmd script
---
output: pdf_document
---
```{r setup, include=FALSE}
library(gridExtra)
```
```{r, echo=FALSE}
car_tbl <- tableGrob(mtcars[1:10,])
grid.arrange(car_tbl, car_tbl, car_tbl)
```
You can see how the tables overlap each other. There seems like there are actually a few issues comprising my problem.
How do I use the options of tableGrob and grid.arrange to keep the tables from overlapping.
How do I make sure nothing is cut off? In other words, how do I set the graphic to take the whole page if I need it too?
How can I re-actively shrink the text of the plot to fit on one page?
How can I set the size of the page to whatever size I want? Are there options set the knitr document to print to a pdf page of any size I want? Perhaps poster size if I need it to?
There are different angles to approach your question. Here's a working example with three tables fitting in one chunk placed on a pdf of size A2.
---
output: pdf_document
geometry: paper=a2paper
---
```{r setup, include=FALSE}
library(gridExtra)
```
```{r, echo=FALSE, fig.height=10}
car_tbl <- tableGrob(mtcars[1:10,])
grid.arrange(car_tbl, car_tbl, car_tbl)
```
To address your questions specifically,
1. How do I use the options of tableGrob and grid.arrange to keep the tables from overlapping.
Their overlap had more to do with the default fig.height set by knitr.
2. How do I make sure nothing is cut off? In other words, how do I set the graphic to take the whole page if I need it too?
Make sure the figure height and page are big enough for the table.
3. How can I re-actively shrink the text of the plot to fit on one page?
It's not trivial, but I guess it could be done. I doubt it's a good idea though (for typographical reasons): typically the font size should be set, and if the table doesn't fit, it should be split into several pages (there's an example in a link I provided).
3. How can I set the size of the page to whatever size I want? Are there options set the knitr document to print to a pdf page of any size I want? Perhaps poster size if I need it to?
It's a latex question, which in the context of Rmd documents means that you could pass these layout options to latex via rmarkdown and pandoc, typically as options for the geometry package.