One underappreciated feature in R is the ability to easily create beautiful reports using Markdown. Markdown files contain a combination of code and text, allowing you to write your analysis alongside your code and publish both the analysis document and code in a wide variety of formats with little effort.

Why Markdown makes life easier

By combining your code and your documentation, Markdown files in R help you supercharge your analysis by:

  • Use multiple languages in a single document to explore the data
  • Weave your code and analysis together in a fluid and intuitive manner
  • Bundle your code with your analysis, allowing other people to understand your approach and replicate your work
  • Quickly and easily create professional looking reports using the outputs (tables, graphs, etc) of your analysis in R
  • Move between multiple export formats (HTML, PDF, Word, PowerPoint) quickly and easily

It helps to understand what the end goal is when learning to use new tools. Consequently, I recommend having a quick look at the final output from a simple R Markdown file, and the code below, in order to set the context for the rest of this post.

Getting started with Markdown

To begin, you’ll need to create a new Markdown file in R studio or create a .Rmd file in your text editor of choice.

The header

At the top of your new Markdown file you’ll want to insert some text that looks like this:

title: "R Markdown Example"
author: "Birch & Bison Consulting"
date: "December 23, 2018"
output: pdf_document

This block sets the title, author, and date of the file, and also specifies which format the final report should be created in when the file is published.  There are many formats to choose from including:

  • html_document – HTML documents for publication on the web
  • pdf_document – PDF documents for sharing and printing
  • word_document – Microsoft Word documents for sharing and printing
  • powerpoint_presentation – Microsoft PowerPoint documents for presentation

There are many other formats to choose from, although some require the installation of additional libraries and / or software. For this demonstration, we’ll use the html_document format since it is the most widely supported.

The content

Once you’ve added the header to your file, you can start writing your documentation.  Simply start writing below the header block and it will show up on the screen as paragraphs of unformatted text.

Markdown syntax

If you want to format your text, such as adding headers, bolding or italicizing text, you’l need to use Markdown to specify those formats.  Luckily, the syntax for Markdown is simple and easy to learn.  Headers are prefix by one or more hashes, italicized text by asterisks, and bold text is surrounded by two asterisks. Using Markdown you can also create block quotes, lists, hyperlinks, and other formats. Here are examples of the more common styles that you’ll want to incorporate into your documents.

# This is a level 1 (large) heading
## This is a level 2 (medium) heading
### This is a level 3 (small) heading

Three dashes creates a horizontal line

*This text is emphasized (italics)*
**This text has strong emphasis (bold)**

> This is a block quote

- Putting dashes in
- front of text creates
- an unordered list

1. Putting numbers and
2. periods in front of text
3. creates an ordered list

[This is a hyperlink](

To learn more about other formats you can use, please read the Markdown documentation.

Adding code chunks to your Markdown file

As mentioned earlier, the beauty of markdown files is their ability to weave together code and text, allowing you to perform calculations and then explain and interpret the results in a fluid intuitive manner. The actual code is contained within “chunks” which look like this:

```{r example}

series <- 1:10
series * 2


Anatomy of a code chunk

Code chunks begin and end with three grave accents (```). After the opening set of grave accents is a set of curly brackets and in that set of curly brackets you define the language for your code chunk (in this case, r) and the name of your code chunk (in this case, example). You can also set various display and other options for the code chunk here, which we’ll cover a bit later.

Code chunk output

When it is time to publish your document (also known as ‘knitting’ it), not only will the code from your chunks be displayed in your final document, but any output it generates will be shown as well. As an example, the output of the code and output from the block above would be displayed in your final document like this:

series <- 1:10
series * 2

##  [1]  2  4  6  8 10 12 14 16 18 20

The code is shown, with the output from the code below.  The output, by default, is escaped with two hashes so that if you copy and paste the code and output into R and run it, R won’t try to execute the output (and inevitably generate some colorful errors).

Display options for code chunks

Depending on the relevance of your code, you might want to suppress the display of your code and / or it’s results in your final document.

Hiding the code, but displaying the output

If you want to hide your code but only display the output, you can specify this by adding the echo = FALSE argument to your chunk definition like this:

```{r example, echo = FALSE}

series <- 1:10
series * 2


This is commonly used to display tables and graphs in reports, but not show the code used to actually create the tables and graphs since it is either irrelevant or inconsequential.

Hiding the code and the output

If you want to hide your code and output, you can specify this by adding the include = FALSE argument to your code chunk definition like this:

```{r example, include = FALSE}



This is a good way to hide background work or library imports that don’t have any effect on your overall analysis.

Suppressing the hashes from the output

If you don’t want the output of your code to be prefixed by hashes, you can add the comment = NA argument

```{r example, comment = NA}

series <- 1:10
series * 2


Putting it all together

Below is an Rmd document that shows the river levels in the city of Winnipeg during the 1990s and the flood of 1997. You can see what the final (knit) output of this file looks like at Winnipeg river levels.

title: "River levels in Winnipeg from 1990 to 1999"
author: "Birch & Bison Consulting"
date: "December 23, 2018"
output: html_document

```{r setup, include=FALSE}

# This is a hidden code chunk, both the code and output are not shown

# Here we are setting our code to display by default going forward
knitr::opts_chunk$set(echo = TRUE)


The 1990s represented an interesting decade in the life of the Red and Assiniboine rivers in [Winnipeg, MB]( The first couple years of the decade were characterized by below average water levels, which all changed in 1997 with 'the flood of the century'.

The impacts of these events are still evident in Winnipeg today. The walkways along the river, built in the early 1990s, are set close to the water and flood more frequently than initially projected. The [flood of 1997]( didn't cause significant damage within the city of Winnipeg, but it led to the city further excavating the Red River Floodway to add additional capacity for future floods of that magnitude.

## Water level summary by year

Looking at the mean and max water levels by year, you can see how 1990 and 1991 were well below average, and 1997 was a significant flood event compared to other years.

```{r libraries, include = FALSE}

# This is a hidden code chunk
# The 'include = FALSE' argument hides the code and any output it creates



```{r 1990_levels, comment = NA}

# This is a normal code chunk
# By default, both the code and its output will appear in the knit document
# The hash marks in front of the codes output have been disabled for a cleaner appearance

# Download the historic water levels for the Red River in Winnipeg
levels <- read.csv('$limit=3650&$offset=0')

# Print a summary table by year for 1990 to 1999
levels %>%
  filter(substr(reading_date, 1, 3) == '199') %>%
  group_by(substr(reading_date, 1, 4)) %>%
  summarize(Observations = n(), Mean = mean(james_feet), Min = min(james_feet), Max = max(james_feet)) %>%
  rename(Year = `substr(reading_date, 1, 4)`)


## The flood of 1997

The flood of 1997 was considered a 1:100 year event. Even with the operation of the Red River Floodway, the water level in the city of Winnipeg peaked at 24.5 feet on May 3rd.

```{r echo = FALSE}

# This is a code chunk where only the output will be displayed, not the code

# Summarize the data to create a graph
graph_levels <- levels %>%
  filter(substr(reading_date, 1, 4) == '1997') %>%
  group_by(reading_date) %>%
  summarise(james_feet = mean(james_feet)) %>%

graph_levels$reading_date <- as.Date(graph_levels$reading_date, format="%Y-%m-%d")

# Draw the graph
plot(graph_levels, type='l', main='1997 river levels by day', xlab='Date', ylab='Feet above winter average')


The flood caused $500M of damage within the province of Manitoba, largely within the communities surrounding Winnipeg. While the floodway was effective in limiting the water levels within the city of Winnipeg, some have criticized its design as having raised water levels in the outlying communities.

2 Replies to “Quickly create polished, professional reports with Markdown and R

  1. Hi there,
    thanks for taking the time to put together an interesting article on this.
    I have been using (fighting with, really) Markdown to generate word documents containing customer reports and I have been able to achieve most of my “dreams”. I created a “model” document and set it with all the frills I wanted, like:
    – layout =landscape (Forced in sample document as well as in the start of the .RMD file) – failed to deliver
    – default table style as a plain table with all borders painted (Forced in sample document ) – failed to deliver
    – default page numbering in the footer using style accent1 (Forced in sample document ) – failed to deliver
    – default headings styles (Forced in sample document ) – delivered
    In the start of the RMD file I use I have the following:
    title: “Capacity and Availability for Data and Internet Services”
    output: word_document
    reference_docx: TestFormat.docx
    classoption: -landscape

    Any hints on where I should look to work out what I am not doing correctly?

Leave a Reply

Your email address will not be published. Required fields are marked *