Chapter 10 Markdown and rmarkdown
10.1 What is markdown
Markdown is a language to create text documents. You are probably familiar with modern text processors, such as Google Docs or Microsoft Word. Such word processors allow you to create beautiful text that may contain images, use multiple fonts and be rendered in multiple columns.
Markdown is not like this. Not at all. But it can create beautiful text too,
although its capabilities are rather limited. Also, it is not a text
processor.
Markdown is a markup language. So it is a language that
has special codes for formatting text. When you write markdown, you
cannot just create bold text, instead you have to include the
formatting codes around the text you want to be bold (here double
asterisks, as in **bold text**
). And then we have to render it
into something, e.g. into html,
where the formatting codes are transformed into the
corresponding format, like double asterisks are transformed
into bold font.
Why do we need such language that may feel like the text processing tools of 1980-s? There are several reasons. It is true that modern word processors are currently the dominating way to create documents. But they are not good tools to create all documents.
- Markdown does not require a dedicated word processor. You can edit markdown documents in every text editor (such as RStudio). The file format is plain ASCII text, the simplest way to store text. So every programmer can use their favorite editors to write documents.
- Markdown can be integrated into various simple document processing environments, such as discord chat or documents on Github.
- Markdown is simple to write and very easy to learn. There are other markup languages, such as HTML and LaTeX that are much more powerful, but also much more complicated to use.
- Markdown formatting codes are visible. So for instance, you can
use both italics and bold, typed as
_italics_ and **bold**
. Now if my cursor is on the space beforeand
, I can immediately tell that this space is not italic–it is outside of the italic formatting codes (underscores). This avoids nasty surprises in text processors where I start writing and discover that my text is formatted in an unexpected way. - Word processor file formats tend to be quite complicated. If you want to generate a word processor document not manually but through a computer program, you find this to be a formidable task. And this is exactly what we do with rmarkdown below.
- Because word processor file formats are complicated, they are not easy to combine with version control systems, such as git. Word processors include their own revision controls, but these are fairly limited and do not integrate with git if that is what you use for the rest of your project.
So Markdown provides a simple way to describe the desired formatting of text documents while leaving rendering for other software. Rendering means transforming markdown text into the final format, such as HTML or pdf, that actually displays the formatting in desired way (instead of format codes). So in markdown you do not create layout, instead of that you tell what kind of layout you want. In fact, this book is written using markdown (with some help of HTML)! With only a small handful of options, markdown allows you to format to your text (like bold and italics), and well define structure of the document (such as headers and bullet-points).
There are many programs and services that support the markdown, including GitHub, Slack, discord, teams, and StackOverflow (though note the syntax and capabilities vary somwhat across programs). In this chapter, we’ll learn the basic markdown syntax, how to use it to produce readable documents, and how to combine it with R code.
10.2 The first taste of markdown
Markdown is a lightweight markup language that is used to format and structure text. It is a kind of “code” that you write in order to annotate plain text: it lets the computer know that “this text is bold”, “this text is a heading”, etc. Compared to other markup languages, Markdown is easy to write and easy to read. In my opinion, it is much easier that what normal word processors offer, and hence I am sometimes using markdown syntax even in contexts that do not support markdown, such as Google docs. And because markdown is simple to include, it’s often used for formatting in web forums and services (like Wikipedia or Discord). As a programmer, you’ll use Markdown to create documentation and other supplementary materials that help explain your projects, rmarkdown (see Section 10.4) is also a good way to write reports.
The basic markdown workflow to compose documents includes both writing and rendering. This differs from the modern word processors, where these two elements are combined into a single one: if you insert a bold letter into your document, you’ll immediately see that it is bold. In markdown, you need to first write the letter with bold markers, and thereafter to render it into something (e.g. html) that can actually display it as bold. These two steps are separated.
10.2.1 Text Formatting
At its most basic, Markdown is used to declare text formatting options. You do this by adding special symbols (punctuation) around the text you wish to “mark”. For example, if you want text to be rendered as italics, you would surround that text with underscores (_
): you would type _italics_
, and a program would know to render that text as italics. You can see how this looks in the below example (code on the left, rendered version on the right):
There are several ways you can format text:
Syntax | Formatting |
---|---|
_text_ |
italics with underscores (_ ) |
**text** |
bold using two asterisks (* ) |
`text` |
inline code with backticks (` ) |
~~text~~ |
~ ) |
10.2.2 Text Blocks
But Markdown isn’t just about adding bold and italics in the middle of text—it also enables you to create distinct blocks of formatted content (such as a header or a chunk of code). The table shows the most important options:
Syntax | Formatting |
---|---|
# |
Header (use ## for 2nd-level, ### for 3rd, etc.) |
``` |
Code section (3 back ticks) that encapsulate the code |
- |
Bulleted/unordered lists (hyphens) |
> |
Block quote |
See more about markdown tools in Section 10.3.
10.2.3 Rendering Markdown
In order to view the rendered version of your Markdown-formatted text, you need to use a program that converts the Markdown into a formatted document. Some of the websites (like GitHub or StackOverflow) and multiple chat programs (like Slack or Discord) will do it automatically. Some text editors do it as well, but other times you need to compile it to html first.
RStudio has good support of markdown. In particular, you want to tell it you open a new markdown file (File → New File → Markdown File). Thereafter, you can use the preview button, visible on the toolbar when working with markdown files. However, later we work mostly with rmarkdown files (see Section 10.4) that need to be handled slightly differently.
Other options for rendering Markdown include:
Many editors (such as Visual Studio Code) include automatic Markdown rendering, or have extensions to provide that functionality.
There are a variety of online Markdown editors that you can use for practice or quick tests. Dillinger is one of the nicer ones, but there are plenty of others if you’re looking for something more specific.
There are also a browser extension that will render Markdown files for you.
Unfortunately, the rendered result and the syntax may differ slightly, depending on what tools you use to work with markdown.
10.3 Markdown syntax
The basic markdown syntax is rather simple. Below we discuss structure, lists, text formatting, and finally images and tables.
10.3.1 Structure
Text structure tells the renderer what is this text, and let’s the renderer decide how to display it. As structure, we normally mean various section titles, but also paragraphs, pre-formatted text and other similar features.
Text structure can be marked by headings, paragraphs and line breaks:
# Heading
## Sub-heading
### Another deeper heading
#### Fourth level heading
These are normally rendered with big and bold font, with the first level headings being the biggest and boldest.
Line breaks are ignored. Paragraphs are separated by a blank line.
Two spaces at the end of a line leave
a
line
break.
Paragraphs are separated by a blank line. Normal line breaks are ignored, so you can break lines wherever you want.
Line
breaks
are
ignored.
Paragraphs are separated
by a blank line.
Two spaces at the end of a line leave
a
line break.
A dedicated line break can be done by ending the line with double spaces–the second paragraph in this example contains such double-space line ends, these are unfortunately not visible here.
>
in the beginning of the line:
This is a quote:
A clever man commits no minor blunders
– Goethe
This is a quote:
> A clever man commits no minor blunders
-- Goethe
In this example, the > A clever man...
is a quote, while the lines
before and after it are not. Quote is normally marked somewhat
differently than the rest of the text. It is widely used in online
forums, where you can quote the text you are replying to.
above
below
A horizontal rule can be created with three dashes:
above
---
below
These are useful to separate blocks of text where an new section would be impractical.
One special structure element that we’ll use a lot later are code blocks. In plain markdown, these is not actually code blocks, but just “pre-formatted text”, a piece of text that is displayed as-is, with no additional formatting applied, and where spaces and line breaks are preserved as in the original. Code blocks are rendered using fixed-with font where all letters (including “i” and “m”) are of the same width. This also let’s you use it to display various other things instead of code, such as ascii art or poems.
Code blocks are marked with three backticks before and after the block:library(magick) # install it first
cheatsheet <- image_read_pdf("cheatsheet.pdf")
plot(cheatsheet)
```
library(magick) # install it first
cheatsheet <- image_read_pdf("cheatsheet.pdf")
plot(cheatsheet)
```
10.3.2 Lists
Structured text, such as reports, commonly use lists. There are two types of lists: non-numbered (bullet lists) and numbered lists.
Here are fruits: leave a blank line next
- apples
- oranges
- pears
- sublists are indented by 4 spaces
- small pears
- medium pears
Bullet lists can be marked with asteristisks (or dashes) at the beginning of the line:
Here are fruits: leave a blank line next
* apples
- oranges
* pears
- sublists are indented by 4 spaces
- small pears
- medium pears
Normally, you need to leave one blank line above the list, otherwise it will not be rendered as a list, but just sentences that contain asterisks.
Note that lists can be nested–the nested list must be indented by 4 (four) spaces right of the parent list.
Fruits in priority order:
- mangoes
- oranges
- pears (will be rendered as “3.”)
- sublist-starts from “2”
- small pears
- medium pears
Another widely used list is numbered list. These can be done by just preceding lines with numbers:
Fruits in priority order:
1. apples
2. oranges
4. pears (numbering will be fixed)
2. sublist-starts from "2"
3. small pears
3. medium pears
Markdown normally fixes the numbering, so whatever numbers you put in front of your lines, the result will be “1.”, “2.”, etc… But if you start your numbering from “2.”, the you will get “2.”, “3.”, etc.
Exercise 10.1 Write a numbered list of cities. Under at least of one of the cities, write a list of restorants in that city (as a non-numbered sublist).
Feel free to invent!
10.3.3 Text
There are multiple ways to format individual words, or parts of the word.
Underscore marks italics, double asterisks bold, and double tildes striked through text:italic
bold
bold italic
strike through
_italic_
**bold**
_**bold italic**_ ~~strike through~~
(There are other ways to achieve these attributes.)
[link text](url)
. For instance:
Here’s an example
Here's [an example](http://example.com)
The link text will be the visible (and often rendered blue) text that you can click on, and the click will lead you to the url.
here is a text example with inline code
.
`inline code`. here is a text example with
Remember: backtick is the character next to number “1” on the US keyboard.
10.3.4 Images and tables
More often than not, we want to illustrate our text with images.
Fortunately, this is easy.
Images can be inserted by ![](image.jpg)
:
![cat on keyboard](img/markdown/cat-keyboard.jpg)
The anatomy of the markdown command is as follows:
!
tells markdown to actually display the image in text, not just a clickable link. (Note: the syntax is otherwise the same as for web links.)[]
can contain the “alternate text” attribute, the text that the browser renders when it cannot render the image. This may happen if you have got the file path wrong, or if you are using screen reader, a search engine or a web scraper.(image.jpg)
contains the actual image, either file name (possibly with a path), or url. For instance, the same cat image can be displayed straight from wikimedia using![cat on keyboard](https://upload.wikimedia.org/wikipedia/commons/a/aa/Cat_keyboard.jpg)
.
Note that unlike in R code, the file name must not be quoted!
Another type of commonly used illustration is tables. Tables are somewhat inconvenient to create in markdown, but it is good enough for small and simple tables. But here is a small example:fruit | quantity | price |
---|---|---|
apples | 3 | 6 |
oranges | 4 | 8 |
bananas | 1 | 2 |
| fruit | quantity | price |
| -------- | :------: | ----: |
| apples | 3 | 6 |
| oranges| 4 | 8| |bananas|1|2|
The table defines three columns, labeled fruit, quantity and price. The next line, that of dashes, defines the indentation. The first column is lef-justified, quantity-column is centered, and price-column is right-justified.
The first line (apples) is written in a good and clear manner, the oranges-line lacks some spacing, and bananas is written with no spacing at all. However, the renderer ignores spaces and displays all these columns in an equally pleasant manner.
For more thorough lists of Markdown options, see the resources linked below.
Many chat programs, such as Slack and discord will allow you to use markdown as well for quick text formatting. They typically support different fonts, such as bold and italic, but not more complex features like tables.
10.4 What is rmarkdown?
So far we have learned both markdown and R programming. Both of these methods have their strong and weak sides. Markdown is good for creating simple webpages with some design features like titles, images and block quotes. R however does nothing like that. R can just compute and create plots.
But what if we want to do both? After all, many reports and other documents contain both titles and bullet lists, but also various numbers and figures that are computed based on data. Obviously, we can compute these numbers in R and just copy over to the document. But in practice, it is hardly ever the case that you can just copy the results to your document. Almost always you must do the computations multiple times as you fix errors, get better ideas and new data. Results in a research paper may have to be updated hundreds of times. Copying all these numbers manually is a lot of work, copying these hundreds of times without errors is more than any human can do.
Another motivation is to have access to both code and results. In many cases (e.g. when grading homework 🙂), one wants to see both how certain results are done (the code) but also what are the results. This is hard to do in code file–you can add results as comments, but those are not easy to read, and must be re-done in a similar way like figures in ordinary text.
Rmarkdown offers solution to both of these problems. You can write text about your results and both the text and results will be in the final rendered version. And when you re-process it, it will automatically redo all the results with no manual work needed. Depending on the settings, you may also have the original code visible in the final document, this is a good idea with homework, but probably not when submitting the quarterly report to your boss. As an additional bonus, you also have now your code in the same document (although it may not be visible in the final version), so one can go and check how exactly did you compute the figures.
The idea of rmarkdown is to mix markdown (this is good for writing) and R (good for computing). So as a result we can write text that contains all the bells and whistles that markdown offers, but also mix it with R code, and more importantly, results of this code. The figure below shows an example rmarkdown document being written (left), and the resulting html in browser (right). Note how R code has been replaced by the corresponding output, in particular the plot. One can also see the familiar elements from rendered markdown, for instance bold and italic text.
Technically, rmarkdown is a markdown document that contains normal markdown text mixed with code chunks, chunks of R code that will can be run by R like any other code. Processing rmarkdown takes two steps. The first one is knitting, i.e. running the R code and inserting its output into the document, this results in a plain markdown document. Knitting is done by R using knitr package. Thereafter one has to render the markdown in a similar way as ordinary markdown. The final result can be html or pdf document, different types of slides, or even MSWord file. This is again done by R using rmarkdown package and pandoc app.
10.5 R Markdown and RStudio
The most convenient way to create and process rmarkdown files is by using RStudio. It includes all the necessary packages and software, and provides easy shortcuts to convert the whole document into the final document.
10.5.1 Creating Rmarkdown Files
The easiest way to start a new R-Markdown document in RStudio is to use the File > New File > R Markdown menu option:
RStudio will then prompt you to provide some additional details about what kind of R Markdown document you want. In particular, you will need to choose a default document type and output format. You can also provide a title and author information which will be included in the document (no worries if you don’t know how to call your document– you can easily change it later). This chapter will focus on creating HTML documents (websites; the default format)—other formats may require additional software.
Once you’ve chosen your desired document type and output format,
RStudio will open up a new document file for you. The file contains
some example code (a template) to remind you the basic rmarkdown
syntax. Rmarkdown files typically have extension .Rmd
10.5.2 Rmarkdown Structure
Rmarkdown files normally begin with header information like
---
title: "My Night at Three Pints Inn"
author: "Ji Gong"
date: "April 28, 2021"
output: html_document
---
This tells R Markdown details about the file and how the file should be processed. For example, the title
, author
, and date
will automatically be added to the top of your document. You can include additional information as well, such as whether there should be a table of contents or even variable defaults.
- The header is written in YAML format, which is yet another way of formatting structured data similar to
.csv
or JSON (in fact, YAML is a superset of JSON and can represent the same data structure, just using indentation and dashes instead of braces and commas).
Below the header, you will find two types of content:
Markdown: normal Markdown text like you learned in Chapter 3. For example, you can use two pound symbols (
##
) for a second-level heading.Code Chunks: These are segments (chunks) of R code that look like normal code block elements (using
```
), but with an extra{r}
immediately after the opening backticks. The{r}
is a crucial marker and tells RStudio that code in these blocks must be executed, not just displayed.RStudio provides a convenient keyboard shortcut,
Ctrl-Alt-i
, for creating new code chunks.Inline code chunks: it is also possible to write short code snippets that output a single word or number on the same line as text. For instance, you may write text like
"we have
`r nrow(data)`
observations..."
. This results in a line “we have 150 observations…” (or whatever many observations does your data contain).
10.5.3 Knitting Documents
RStudio makes it easy to compile your .Rmd
source code
into the actual document. This process is called “knitting”.
Simply
click the Knit button (keyboard shortcut Ctrl-Shift-K
)
at the top of the script panel.
This will generate the document (in the same directory as your .Rmd
file), as well as open up a preview window in RStudio.
If you chose HTML as your desired output type, RStudio
will knit your .Rmd
into a .html
file. HTML stands for
HyperText Markup Language and, like Markdown, is a
syntax for describing the structure and formatting of content (though
HTML is far more extensive and detailed). In particular, HTML is a
markup language that can be automatically rendered by web browsers,
and thus is the language of internet.
RStudio will display the content automatically in a simple built-in
browser, if you want to use your “big browser”, you can click the
“Open in Browser” button, or just double-click on the html file on
your file manager.
10.6 R Markdown Syntax
What makes R Markdown distinct from simple Markdown code is the
ability to actually execute your R
code and include the output
directly in the document. R
code can be executed and included in
the document in blocks of code, or even inline in the document!
10.6.1 R Code Chunks
Code that is to be executed (rather than simply displayed as code) is
put into code chunk-s. To specify a code chunk, you need to
include {r}
immediately after the backticks that start the code
block (the ```
). So code chunks should begin with
```{r}
instead of ```
.
On the Figure here is an example
code chunk. Note the beginning marker
```{r}
and end marker ```
. All lines between these
markers are considered to be R code and executed. Depending on the
options, the code may be replaced by its output in the final document,
resulting in
## [1] 3
Note that by default, the code chunk will render any raw expressions
(e.g., x
)—just like you would see in the console if you
selected all the code in the chunk and used ctrl-enter
to execute
it.
Exercise 10.2 Create a new rmarkdown document. Inside a document, write a for-loop that prints numbers 1 to 10.
How will the result be rendered?
10.6.2 Inline Code
In addition to creating distinct code blocks, you may want to execute R code inline with the rest of your text. In this way you can insert individual computed values, such as results you computed in your previous code chunk, directly in your text. So if your data or computation change, re-knitting your document will update the values inside the text without any further work needed.
As code chunks are “made” of markdown code blocks, inline code chunks
are “made of” markdown inline code, marked by single backticks
(`
). However, you need to put the letter r
immediately after
the first backtick, and follow it with a space and R code, as
`r 3 + 4`
. When you knit the text above, the
`r 3 + 4`
would be replaced with the number 7
.
The example here shows two inline code chunks. Both will be executed and replaced by their output, here 1.4142136 and 1.414. So the final output will look like
Square root of 2 is 1.4142136. Note–you may want for format it better, as 1.414.
The example also hints that when injecting numbers that are not integers in text, you normally want to round them to a fewer number of digits.
Note you can also reference values computed in the code blocks
preceding your inline code; it is a good idea to do any sizeable
calculation in a (potentially invisible) code block, store the result
in a variable, and then simply inline that variable with e.g.,
`r my.variable`
.
In order for the inline code chunks to work, the text must fit on the
single line. So `r 1 + 1`
works, but when the
chunk is broken to two lines:
`r
, it will just displayed as ordinary text.
1 + 1`
10.6.3 Chunk options
It is sometimes a good idea to make both code and results visible, e.g. when presenting your coding exercises. However, in other cases either code is undesireable (e.g. when writing the quarterly report to your boss), or maybe you do not want the results to show up instead. Rmarkdown offers a large number of chunk options do fine-tune the code execution and displaying behavior. There are two ways to specify chunk options: for a given chunk, and globally.
10.6.3.1 Chunk-specific options
Chunk options are written in the code chunk header, inside of the
{r}
part. They are normally a comma-separated lists of name-value
pairs, e.g. echo=FALSE
(this options suppresses displaying code in
the final document).
The code chunk example here has a single option (echo=TRUE), i.e. to
show the code in the final document. It also has a name
(pipe-example). The name will be displayed during the knitting
process and it helps in troubleshooting. If you want to set more than
a single option, you need to separate those with commas. In this
example, you may write ```{r pipe-example, echo=TRUE, error=TRUE}
to indicate that eventual errors should not break
knitting process but the error message should show up in the final
document instead.
Here is a brief review of the code chunk options. You write code
chunks as ```{r chunk-name, option=value, option=value, ...}
.
The first word after
r
(and before comma), here chunk-name, is the name for the chunk. Names are good to track knitting, they can also be referred from another chunk, so you can re-use your code chunks. However, an rmarkdown document can only contain a single code chunk with a given names, so you have to keep it in mind and change names when copy-pasting your code. If you do not give a name to the chunk, it will be named like unnamed-chunk-2.echo
indicates whether you want the R code to be displayed in the document (e.g., if you want your readers to be able to see your work and reproduce your calculations and analysis). Value is eitherTRUE
(do display; the default) orFALSE
(do not display).message
indicates whether you want any messages generated by the code to be displayed. This includes print statements! Value is eitherTRUE
(do display; the default) orFALSE
(do not display).error
indicates whether you want the knitting to stope and display the error message in case it runs into an error in a code chunk, or you want it to continue and display the error message in the final document. Values are isTRUE
(continue and display the message in the final document) orFALSE
(stop, and display the error on the rendering window).For small documents, it is typically easier to display the error message in the final document (error=TRUE). But sometimes knitr refuses to complete the document at all if there are errors, and then you cannot even see what the problem is unless you send errors to the console (error=FALSE). The latter is also adviseable in case of larger documents where you cannot easily check everything for potential errors. It is embarrassing to send your quarterly report to your boss, only for her to discover that it contains big red error messages instead of final resutls!
eval
indicates if you want the included code only to show (eval=FALSE) or also the execute (evaluate) and produce results (eval=TRUE). If you want to show code that cannot be executed, e.g. because it requires data that cannot be accessed, you can show it with eval=FALSE.
There are many more options for creating code chunks.
10.6.3.2 Global chunk options
The global chunk options are otherwise similar to ordinary chunk
options, but they apply to all following code chunks. But they have
to be specified separately, using knitr::opts_chunk$set()
function.
This is normally done at the top of the document in a separate code
chunk.
For instance, if you want to hide all code in your document (but keep the results visible), then you can write a following code chunk:
10.7 Troubleshooting knitting problems
R-markdown documents are easy to create, and if you write your code correctly, then knitting is just as simple as a keypress. But unfortunately, it is hardly ever the case that one gets the code right in the first try. And code in rmarkdown is harder to debug than just plain R code. There are a few reasons for that.
10.7.1 Finding errors
Most importantly, the output of your code may not show up neither on screen nor in the document. While you run a plain R script, then the output always appears in the RStudio console. But when knitting, the output may want to your document instead. However, if an error appears then you cannot see output in the document… There are different solutions if you run into this problem:
- Test your code first outside of rmarkdown environment. This is often a good idea, but sometimes it is hard to build a similar environment than the code in your document. For instance, the working directory may be different for knitting and for RStudio console, and hence the file names may not work.
- Use the
error = TRUE
chunk option (see Section 10.6.3 below). This does not break knitting but makes the error message, together with the eventual output visible in the final document. Unfortunately, this does not work with all errors. - Add labels to you code chunks (again, see Section 10.6.3 below) so you can see in which chunk the problem occurs.
- Remove part of the code from the misbehaving chunk until it works. This may be a slow and tedious process, but it is more general and can be applied to pretty much every coding context.
We also suggest that you write more complex code in a separate script
and then use source()
to load script into your document.
This makes it easier to test the more complex data processing outside
of the main document. It also separates data processing from the final
text, this is often considered a good practice.
10.7.2 Knitting is a separate process
A common source of problems is that knitting is a separate process, not the one that that is available as “Console” in RStudio. It is a separate R program that, in particular, has its own working directory. This is the directory where your markdown file is located. It may or may not be the same as the working directory in your Rstudio console!
Knitting is a separate process with a separate working directory!
Besides a potentially different working directory, the knitting
process does not have access to your workspace variables, nor the
packages that you have loaded in console. You need to load data
separately, you need to compute all values in the knitted document,
and you need to load every package with the library()
command in
the rmarkdown document. This is to ensure that you can re-compile
your document and get the same result, no matter what other things you
have done in RStudio.
Knitting does not have access to your workspace variables and loaded packages!
10.7.3 Some interactive commands do not work in knitting
Finally, there are commands that do not work when using in
knitting. This includes certain interactive commands
that cannot be included in documents, such as
install.packages()
. As it is normally not a good idea to
install packages in documents anyway, we do not discuss the
workarounds.
Use the error message as a useful reminder that one should just load,
not install packages in markdown documents!
Do not use install.packages()
in rmarkdown document!
As a generic advice, you should knit your document frequently and fix the problems immediately before you continue your work. An new error was most likely caused by something you did just a moment ago, and there are good chances that you still remember what did you do. It is harder to fix it later.
10.8 Rendering Data
R Markdown’s code chunks let you perform data analysis directly in your document. It is straightforward with simple numbers, but sometimes you may want to include more complex output in your text. This section discusses a few tips for doing this.
10.8.1 Rendering Strings
If you experiment with knitting R Markdown, you will quickly notice
that print()
in a code chunk will generate output that is not very
well suited for a document:
print("Hi there!")
## [1] "Hi there!"
For this reason, you may instead generate the message as a string in a previous code block, and display it afterward using an inline chunk (possibly on its own line):
"Hi there!" msg <-
And display it as `r msg`
: Hi there!
Note that any Markdown syntax included in the string, such as bold
“Hi” in "**Hi** there"
) will be rendered as well–the
`r msg`
is replaced by the value of the expression
just as if you had typed that Markdown in directly. This allows you to
include dynamic styling if you construct a markdown string out of your
data.
Alternatively, you can also use cat()
instead of print()
and set
results=“asis”
option which will cause the output to be rendered directly into the
markdown. So
cat("Hi there!")
will produce
Hi there!
10.8.2 Rendering bullet lists
Because outputted strings render any markdown they contain, it’s
possible to specify complex Markdown such as lists by constructing
these strings to contain the -
or *
symbols, and lines separated
by line breaks (either “”, or you can use
multiline strings):
"
predators <-- Lions
- Tigers
- Bears
"
cat(predators)
Would output a list that looks like:
- Lions
- Tigers
- Bears
Note: you need to set options echo=FALSE and results=“asis” when printing your output. Otherwise the chunck will render as code chunk, not as markdown.
We can also use paste()
(or stringr::str_flatten()
) to make such a
list of of a string vector:
c("Lions", "Tigers", "Bears")
predators <-paste("*", predators) %>% # add '* ' in front of predators
paste(collapse = "\n") %>% # combine into a single string with
# line breaks in-between
cat() # print
- Lions
- Tigers
- Bears
And of course, the contents of the vector (e.g., the text "Lions"
) could easily have additional Markdown syntax syntax to include bold, italic, or hyperlinked text.
If you do this often, consider creating a “helper function” to do this conversion; or see libraries such as pander
which defines a number of such functions.
10.8.3 Rendering Tables
Because data frames are such central features for data analysis,
Rmarkdown includes tools to easily render data frames as
Markdown tables
via the
knitr::kable()
function.20
This function takes as an argument the data frame you wish to render, and it will automatically convert that value into a Markdown table:
data.frame(x = 1:3, y = c("a", "b", "c"))
df <-::kable(df) knitr
x | y |
---|---|
1 | a |
2 | b |
3 | c |
kable()
supports a number of other arguments that can be used to customize how it outputs a table.
And of course, if the values in the dataframe are strings that contain
Markdown syntax (e.g., bold, italic,
or hyperlinks), they will be rendered as such in the table!
So while you may need to do a little bit of work to manually generate the Markdown syntax, it is perfectly possible to dynamically produce complex documents based on dynamic data sources!
10.9 R Notebooks
An alternative (or more like a complement) to rmarkdown is to use “R Notebooks”. R Notebooks are very similar to rmarkdown–actually there is no difference in the files itself, just the way how the code chunks are run.
Note that the code chunks have three special buttons at the top-right corner. The green arrow (circled on the image) makes the chunk to be run as a “notebook cell”. This means the chunk is run, and its output is displayed underneath of it–in this figure this is the plot. This is a very handy way to run the individual code chunks, test and debug them, and see what is the output.
But when using rmarkdown documents as notebooks, be aware of the following caveats:
- Notebook chunks are run in the current R instance, the R program
that is running in Console at bottom right pane. Hence the
chunk’s working directory is the same as the current R instance’s
(the one you can check with
getwd()
), and it has access to all your workspace variables and data. This may cause problems when you rely on these things–remember, the knitting process is run in a separate R instance that may have a different working directory and that does not have access to workspace variables. - Rmarkdown documents only work as notebooks inside of RStudio. If, for some reason, you do not use RStudio, then you cannot run it as a notebook. You can still knit though–it just requires a few commands that you do not have to memorize when using RStudio.
If you are running your code as notebooks, it is still advisable to knit your document frequently, in order to avoid too many compilation issues later.
knitr::kable()
is a way to refer to the functionkable()
that lives in knitr package. It is equivalent (mostly) to loading the knitr library withlibrary(knitr)
and then using justkable()
.↩︎