Helpful Rmarkdown Tips

I've been using Rmarkdown to write reports at work. Whenever I start a project I end up having to look stuff up that I've looked up a million times before. The setup ends up taking so much time and brain power that I end up spending half a day on it. So I figured I'd write it up so I don't have to google my face off to get up and running.

Front matter

There isn't much to the front matter until we introduce the pagedown package (see below). To start, I usually want the date to be the date the document was knitted (Sys.Date()). I also want to be able to edit the CSS sytles without having to knit the document again. By default Rmarkdown knits all the CSS into the html document. That isn't ideal for working on the styles. Every time you edit a CSS file you have to reknit the document to see the changes. You can accomplish these two things by adding the following to your front matter:

---
...More stuff
date: "`r Sys.Date()`"
self_contained: false
...More Stuff
---

Knitr Options

Most of the time I write reports that don't include any output but tables and figures. To achieve this you can set all outputs to false in your setup code chunk (the very first chunk after your front matter).

knitr::opts_chunk$set(
echo = FALSE, #prevents code, but not the results from appearing in the finished file.
message = FALSE, #prevents messages that are generated by code from appearing in the finished file.
warning = FALSE #prevents warnings that are generated by code from appearing in the finished.
)

The opening of this code chunk should look like this: ```{r setup, include=FALSE}.

Sometimes this doesn't catch everything. For example if you use source() to load another file, loading the functions will be included in the Rmarkdown file. For those instances you can use ````{r setup, include=FALSE}` to start the code chunk and that will prevent any output.

Pagedown

I like to use the pagedown package for my reports. Instead of a pdf, word document or website it produces a paged html document. You can use CSS to style your final report literally however you want. In other words it gives you more power than than vanilla Rmarkdown. To get up and running with pagedown you can see their docs here.

At a basic level you need to install the package and then in your front matter add:

---
output:
pagedown::html_paged:
self_contained: false ## This self contained statement should replace the one I detailed above.
toc: false
---

Customizing The Default CSS.

Pagedown comes with it's own default CSS that is intended to make books. Out of the box the pages are a weird size and there are blank pages at the beginning and the end of the document.

To customize how your documents will look you can copy the default CSS styles into your project folder and edit them. To find the default styles pagedown provides a function: pagedown:::list_css() (careful to note the three :::). This will list all the CSS files for each of the templates provided by pagedown. For our purposes we need to copy three of them into the same folder that our Rmd file is in. Copy the following:

  • default-fonts.css
  • default-page.css
  • derault.css

I typically put these in a css/ folder in the same folder my Rmarkdown file is in. Something like this:

Rmd/
├─ css/
│ ├─ default-font.css
│ ├─ default-page.css
│ ├─ default.css
├─ document.Rmd

To get your Rmarkdown to recognize them you need to updated your yaml front matter. At this point this should be your entire yaml front matter section.

---
title: "A title"
author: "Michael Schmidt"
date: "`r Sys.Date()`"
output:
pagedown::html_paged:
css:
- css/default-fonts.css
- css/default-page.css
- css/default.css
self_contained: false
toc: false
---

You can rename the .css files to whatever you want so long as they are references in your front matter.

CSS I like to edit

The first CSS that I change alters the page size so that it is letter sized. To change the page size to 8.5in by 11in the first three lines of default-page.css should look like this:

/* page size */
@page {
size: 8.5in 11in; /* var(--pagedjs-width) doesn't work in browser when printing */
}

@page :blank {
display: none;
/* You can also edit this section if you want to remove the blank second page!! */
}

And in default.css the top should look like this:

:root {
--background: whitesmoke;
--pagedjs-width: 8.5in; /* Change this line to 8.5*/
--pagedjs-height: 11in; /* Change this line to 11 */
--color-paper: white;
--color-mbox: rgba(0, 0, 0, 0.2);
--running-title-width: 2.5in;
--screen-pages-spacing: 5mm;
}

There is a bunch more that you can do, like adding custom fonts, but that should get you started with a 8.5 x 11 pagedown document.

Tables with kable and kableExtra

The last thing I always look up is styling tables. At the most basic level, to get a nice HTML table output instead of the R text output you can use kable and kableExtra.

If you are using page down remove or comment out lines 109 to 123 in the default.css file this will ensure that the kable styling gets applied and not the styling from pagedown:

/* Comment out or remove the following starting at line 109 */
table {
margin: auto;
border-top: 1px solid #666;
border-bottom: 1px solid #666;
}
table thead th {
border-bottom: 1px solid #ddd;
}
thead, tfoot, tr:nth-child(even) {
background: #eee;
}
/* knitr::kables styling, see https://github.com/rstudio/pagedown/issues/214 */
.kable_wrapper > tbody > tr > td {
vertical-align: top;
}

Next install kableExtra with install.packages("kableExtra).

Then whenever you have table you want to output in you Rmarkdown document you can use:

table%>%
kbl()%>% ## turn the table into a kable
kable_classic(full_width=T) ## add a table theme.

And you should get a table that looks like this:

Study Design Strata Completed Plots
2015 Study Design 2015 Study Design 13
Field Office Design (2018-2022) Aspen 9
Field Office Design (2018-2022) Grassland 9
Field Office Design (2018-2022) Mixed Conifer 6
Field Office Design (2018-2022) Mixed Mountain Shrub 12
Field Office Design (2018-2022) Pinyon Juniper Woodland 29
Field Office Design (2018-2022) Ponderosa Pine 9
Field Office Design (2018-2022) Riparian 9
Field Office Design (2018-2022) Sagebrush Steppe 38
Field Office Design (2018-2022) Salt Desert 28
Gunnison Sage-grouse Intensification Sage Grouse Intensification 6

And you should have a nice looking table.