Loading [MathJax]/jax/output/CommonHTML/jax.js
+ - 0:00:00
Notes for current slide
Notes for next slide

Improve your R Markdown Skills

Christophe Dervieux - Yihui Xie

Raukr 2022 - 13/06/2022

1 / 37

Who are we?

Short intro

profile picture for Christophe Dervieux

Christophe DERVIEUX • France

RStudio • Software Engineer • R Markdown Team


2 / 37

Who are we?

Short intro

profile picture for Yihui Xie

Yihui XIE • USA

RStudio • Software Engineer • R Markdown Team


3 / 37

Everyone should know rmarkdown among R users. Its principle has not changed since a long time (md + R = Rmd -> output format) quite easy to start (write text, add code chunk, compile) but it can be harder to learn new skill to be more efficient and get full power.

That is where known recipes can help master more advanced skills. R Markdown Cookbook was thought as a non linear documentation.

Also new logo and new pkgdown website

What happens when it renders ?

R Markdown wizard illustration by Alison Horst Source: https://github.com/allisonhorst/stats-illustrations

5 / 37

We often see these rmarkdown little wizard mixing Text & Code to produce document. Aim is to look deeper into this today. This is not so magic. It is juts percieved magic and there are tools to know about under the hood to be able to customize behavior further.

What happens when it renders ?

Diagram showing the different step of rendering

knitr::knit() + Pandoc (+ LaTeX for PDF) = rmarkdown::render()

6 / 37

rmarkdown will run Pandoc & knitr for you.

LaTeX only needed with PDF. tinytex will run it for you.

This is important to know all this because it helps know where to look and what could be tweak. one has to understand what to tweak to make something works as expected.

About the tools

We got you covered!

  • rmarkdown 📦 will install knitr and tinytex for you
  • Pandoc is an external binary tool, included inside RStudio IDE.
  • TinyTeX is the only thing to install if you want PDF output. (tinytex::install_tinytex())

In case you need it: (but you probably won't!)

7 / 37

Best to use TinyTeX as it is tested agains rmarkdown.

Everything should work as expected otherwise. No special tool needed unless for advanced usage.

Missing CTAN packages are installed by tinytex the R package.

Not sure the aim is to be a rockstar but for sure it is to make those three little guy playing together smoothly

How to boost content creation ?

Gif sayins Content is king with an illustration of a king at his desk in front of a computer with a crown dropping on his head.

9 / 37

First thing to focus one: Boost the content of the R Markdown.

Writing long chunk options

New in knitr

About the chunk header syntax #|

Using R syntax (tag = value, comma-separated, arbitrary line-wrapping)

```{r}
#| echo = FALSE, fig.width = 10,
#| fig.cap = "This is a long caption."
plot(cars)
```

Using YAML syntax (tag: value; one chunk option per line)

```{r}
#| echo: FALSE
#| fig.width: 10
#| fig.cap: "This is a long caption."
plot(cars)
```
10 / 37

Read external scripts into a chunk

New in knitr

About the file chunk option

add <- function(x, y) {
x + y
}
```{r, file = 'my_script.R'}
```
```{r}
add <- function(x, y) {
x + y
}
```

Which is still working

```{r, code = xfun::read_utf8('my_script.R')}
```
  • This will fill the content of the chunk

  • Can be used with any engine (R, Python, C++, ...)

  • Can be used with multiple scripts (e.g file = c("foo.R", "bar.R"))

11 / 37

From Bookdown : https://bookdown.org/yihui/rmarkdown-cookbook/option-code.html

Useful for bigger project, or when script already exists.

Construct chunk content from a variable

About the code chunk option

Example: Installation instruction for packages.

```{r, include = FALSE}
pkgs <- c("glue", "fs")
install_code <- sprintf('install.packages("%s")', pkgs)
```
```{r, eval = FALSE, code = install_code}
```

renders without evaluating to

install.packages("glue")
install.packages("fs")
12 / 37

This is just an example and this can be done with any chunk option. It is quite powerful !

Read code chunks from a script

About knitr::read_chunk()

Use a special comment syntax to label code content.

## ---- chunk-label

Ex in my_chunks.R

## ---- my-chunk-a --------
1 + 1
## ---- my-chunk-b --------
plot(cars)
Read an external script to load chunks:
```{r, include=FALSE, cache=FALSE}
knitr::read_chunk('my_script.R')
```
Now the code can be used chunk by chunk, e.g.,
```{r, my-chunk-a, echo=FALSE}
```
```{r, my-chunk-b, fig.height=4}
```
13 / 37

Useful for:

  • sharing common part of code in a script
  • Store all R code in one R file
  • For bigger project often, or when script already exists.

https://bookdown.org/yihui/rmarkdown-cookbook/read-chunk.html

Use Rmd child document

About child chunk option

Reuse the same content across several Rmd documents:

```{r child = "_common.Rmd"}
```

Also used often with include = FALSE to load common setup content as setup chunk in several documents.

Conditionally include some content:

Change `BOSS_MODE` to `TRUE` if this report is to be read by the boss:
```{r, include=FALSE}
# variable impacting the rendering, which could be a parameter of a report
BOSS_MODE <- FALSE
```
Conditionally include the appendix:
```{r, child = if (!BOSS_MODE) 'appendix.Rmd'}
```
14 / 37

This respect chunk option so could be useful for conditionnally eval or not a part of a document.

Also useful to organize project in smaller pieces.

https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html

Dynamically create content

About knitr::knit_child()
(and result = 'asis')

## Regression on `r x`
```{r}
lm(mpg ~ ., data = mtcars[, c("mpg", x)])
```
  • We want to apply one linear regression between mpg and each of other variables of mtcars
    # select other variables than 'mpg'
    x_vars <- setdiff(names(mtcars), 'mpg')
  • We want the result to be included in its in own chapter.
```{r, echo=FALSE, results='asis'}
# select other variables than 'mpg'
x_vars <- setdiff(names(mtcars), 'mpg')
# knit the template for each
res <- lapply(x_vars, function(x) {
knitr::knit_child('template.Rmd',
envir = environment(), quiet = TRUE
)
})
# cat() the knitted output to be included 'asis'
cat(unlist(res), sep = '\n')
```

Can be combined with knitr::knit_expand()

```{r, echo=FALSE}
x_vars <- setdiff(names(mtcars), 'mpg')
res <- lapply(x_vars, function(x) {
knitr::knit_child(text = c(
'## Regression on "`r x`"',
'',
'```{r}',
'lm(mpg ~ ., data = mtcars[, c("mpg", x)])',
'```',
''
), envir = environment(), quiet = TRUE)
})
res <- paste(res, collapse = "\n") # create one string with content
```
`r res`
15 / 37

Quite like child document but a bit different. Can be useful sometimes for programatically create markdown content.

https://bookdown.org/yihui/rmarkdown-cookbook/child-document.html

Reuse a chunk

About chunk label

Here is a code chunk that is not evaluated:
```{r, chunk-one, eval = FALSE}
1 + 1
2 + 2
```
Now we actually evaluate it:
```{r, chunk-one, eval = TRUE}
```

First chunk will be used twice - different options are allowed.

16 / 37

Reuse a figure, Show code in another place that the initial result, show figure in another place than where the plot has been evaluated. Recompute the same content.

https://bookdown.org/yihui/rmarkdown-cookbook/reuse-chunks.html

Use labels to reference chunks

About chunk ref.label

```{r chunk-b, echo = FALSE}
# this is the chunk b
1 + 1
```
```{r chunk-c, echo = FALSE}
# this is the chunk c
2 + 2
```
```{r chunk-a, ref.label = c('chunk-c', 'chunk-b'), eval = FALSE}
```
```{r chunk-a, eval = FALSE}
# this is the chunk c
2 + 2
# this is the chunk b
1 + 1
```
```
## [1] 2
```
```
## [1] 4
```
```r
# this is the chunk c
2 + 2
# this is the chunk b
1 + 1
```
17 / 37

Yes chunk content can be combined. Could be useful to show code in appendix at the end of the document for example.

https://bookdown.org/yihui/rmarkdown-cookbook/reuse-chunks.html

Include content verbatim (1)

New in knitr

About verbatim engine

Let's show an example of Rmd file content:
````{verbatim, lang = "markdown"}
We can output arbitrary content **verbatim**.
```{r}
1 + 1
```
The content can contain inline code like
`r pi * 5^2`, too.

Let's show an example of Rmd file content:
````markdown
We can output arbitrary content **verbatim**.
```{r}
1 + 1
```
The content can contain inline code like
`r pi * 5^2`, too.

See also about knitr::inline_expr() to Show a verbatim inline expression

18 / 37

Include content verbatim (2)

New in knitr

About embed engine

Here is the macros.js content used for remark.js with this xaringan presentation

remark.macros.scale = function(w, alt="") {
var url = this;
return '<img src="' + url + '" style="width: ' + w + ';" alt="' + alt + '" />';
};
remark.macros.scaleh = function(h, alt="") {
var url = this;
return '<img src="' + url + '" style="height: ' + h + ';" alt="' + alt + '" />';
};
Here is the `macros.js` content used for _remark.js_ with this **xaringan** presentation
```{embed, file = "macros.js"}
```
Here is the `macros.js` content used for _remark.js_ with this **xaringan** presentation
```js
remark.macros.scale = function(w, alt="") {
var url = this;
return '<img src="' + url + '" style="width: ' + w + ';" alt="' + alt + '" />';
};
remark.macros.scaleh = function(h, alt="") {
var url = this;
return '<img src="' + url + '" style="height: ' + h + ';" alt="' + alt + '" />';
};
```
  • Language used for code blocks is derived from file extension
  • It can be customized using the lang option
  • Equivalent to using verbatim engine with lang and code chunk options... but simpler to use !
19 / 37

Using any command-line tools in a chunk (1)

New in knitr

About the exec engine

The exec engine allows to execute an arbitrary command on the code chunk content, optionally with arguments.


```{exec, command='Rscript', engine.opts = list(args1 = "--vanilla")}
1 + 1
```
```r
1 + 1
```
```
## [1] 2
```

For details about this new engine, see 124-exec-engine.Rmd in knitr-examples repo.

20 / 37

The exec engine allows to execute an arbitrary command on the code chunk content, optionally with arguments. If any, they are passed to engine.opts and they could be one of the following:

Using any command-line tools in a chunk (2)

New in knitr

More complexe example using awk

1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar Maths 85
5) Hari History 89

Let's try process this file with awk from within our R Markdown document

Let's count how many line contains `Maths`
```{exec, command = "awk", engine.opts = list(args1 = "-f", args2 = "marks.txt")}
/Maths/{++cnt} END {print "Count = ", cnt}
```
  • args1 = "-f" needed to execute the content of the chunk as a awk program
  • args2 is used to pass the text file to process with the program
Let's count how many line contains `Maths`
```awk
/Maths/{++cnt} END {print "Count = ", cnt}
```
```
## Count = 2
```

See 124-exec-engine.Rmd in knitr-examples repo for the different options.

21 / 37

Using some command line tools may require tweaking the exec engine arguments

What about styling outputs ?

Gif of a man in a suits putting a a pink hat with included sunglasses. Text on the gif says 'You don't like my style'

22 / 37

Let's talk about styling content now.

Use CSS from inside a Rmd file

About the css engine

```{css, echo = FALSE}
/* add a blue border */
div.mybox {
border-color: blue;
border-style: solid;
padding: 0.5em;
}
/* Set to blue bold text inside the box */
div.mybox strong {
color: blue;
}
```

Applied directly in the Rmd document without an external css file

Going further: See the js engine to apply JS code the same way

23 / 37

Useful for prototyping, for quick iteration, for single file example echo = false is important if you don't want to show CSS source chunk in output

Use SASS the same way

About the sass/scss engine

What is SASS ?

Sass (https://sass-lang.com) is a CSS extension language that allows you to create CSS rules in much more flexible ways than you would do with plain CSS.

It allows for variables, tweaking functions (called mixins), operations (like /), better CSS rule organisation (nesting, extensions, ...) and more.

24 / 37

External tool used by web developers. Very powerful and this is a skill to learn when doing a lot of HTML. It can do a lot !

But no need to use it directly. Still need to learn the feature and syntax.

Use SASS the same way

About the sass/scss engine

```{css, echo = FALSE}
div.mybox {
border-color: blue;
border-style: solid;
padding: 0.5em;
}
div.mybox strong {
color: blue;
}
```
```{scss, echo = FALSE}
$color1: blue;
div {
&.mybox {
border-color: $color1;
border-style: solid;
padding: 0.5em;
strong {
color: $color1;
}
}
}
```
```{sass, echo = FALSE}
$color1: blue
div
&.mybox
border-color: $color1
border-style: solid
padding: 0.5em
strong
color: $color1
```

In both example, we are using special SASS feature like Nesting and Parent Selector.

25 / 37

The CSS is the one that would be render when using sass on the .scss or .sass file.

No preference on the syntax - it is a personnal choice (and depending on environment.)

Use SASS the same way

Powered by the new sass R 📦

https://rstudio.github.io/sass/


Support is now built-in rmarkdown

26 / 37

Quite new. Allow to use SASS from R. Wrapper around a C library.

Supported in rmarkdown now.

Use SASS the same way

Powered by the new sass R 📦

$color1: blue
div
&.mybox
border-color: $color1
border-style: solid
padding: 0.5em
strong
color: $color1
# Rendering SASS file from R
sass::sass(sass::sass_file("style.sass"))
div.mybox {
border-color: blue;
border-style: solid;
padding: 0.5em;
}
div.mybox strong {
color: blue;
}
27 / 37

Small intro. Best is to look at the pkgdown website.

Use SASS the same way

Powered by the new sass R 📦

External .sass / .scss file can also be passed in the css argument of html_document()


output:
html_document:
css: custom-style.scss

The file will be processed internally by sass::sass_file() and produce a .css automatically.

28 / 37

You can do much more with SASS. It pushes the limit of customization of a document.

How to use it ? Why this CSS example ?

Use custom blocks to style

Powered by Pandoc's fenced divs syntax

::: mybox
Special **important** content
:::

With the previous style applied, it will result in this box in the document

Special important content



<div class="mybox">
<p>Special <strong>important</strong> content</p>
</div>
29 / 37

Pandoc feature. R Markdown knows and extend it. Quite simple to write but quite powerful.

Supported by Visual editor.

Use custom blocks to style

Powered by Pandoc's fenced divs syntax

Attributes and id can be added too, e.g

::: {.mybox #box1 style="text-align: center;"}
Special **important** content
:::

The above add inline style to the div

Special important content



<div id="box1" class="mybox" style="text-align: center;">
<p>Special <strong>important</strong> content</p>
</div>
30 / 37

Allow to style mainly.

Aiming multi formats

About rmarkdown custom blocks for PDF support

::: {.mybox latex=true}
Special **important** content
:::
\begin{mybox}
Special \textbf{important} content
\end{mybox}

Specially supported by R Markdown and not Pandoc.

Create a LaTeX environment as easily as you can create a HTML div.

31 / 37

Extend the Pandoc feature for LaTeX environment. Not done by default in Pandoc. Special feature of rmarkdown.

Aiming multi formats

About rmarkdown custom blocks for PDF support

This requires a LaTeX preamble for this custom environment to render to PDF, e.g using tcolorbox CTAN package.

\usepackage{tcolorbox}
\newtcolorbox{mybox}{
colframe=blue,
halign=center,
boxsep=5pt,
arc=4pt}

To pass to the output format, e.g

output:
pdf_document:
includes:
in_header: preamble.tex
32 / 37

Could also be added in a file directly obviously.

Aiming multi formats

About rmarkdown custom blocks for PDF support

Using the cat engine can help you write the preamble from within the Rmd file

```{cat, engine.opts = list(file = 'preamble.tex')}
\usepackage{tcolorbox}
\newtcolorbox{mybox}{
colframe=blue,
halign=center,
boxsep=5pt,
arc=4pt}
```

This will result in the PDF as this box

33 / 37

Just for showing cat engine usage here;

And try texPreview in source file

Gif with an image from The Fresh Prince of Bel-Air wearing a pink hat and in a position of thinking with right hand of its chin. Text has been added and says 'But what about the blue bold text ?'

LaTeX customization is a topic for another time ! 🙄

34 / 37

What we've learn so far ?

Let's sum up!

Be more powerfull with knitr

  • Include content verbatim from text or files
  • Import code chunk content from a script or from a variable
  • Use Rmd child document to share content in several places
  • Reuse some chunks several times
  • Use any CLI tools on the code chunk content

Customize output style

  • Customize HTML output using CSS and SASS code
  • Create and style custom blocks for HTML and PDF allowing better customization
35 / 37

How to go further ?

and boost even more your skills !

Look at examples

Xaringan Source of this presentation in
cderv/raukr-2022-rmd-skills


36 / 37

Special demo file contains part of what we saw but also other recipes from the cookbook.

Thank you !

37 / 37

Acknowledgement

37 / 37

Who are we?

Short intro

profile picture for Christophe Dervieux

Christophe DERVIEUX • France

RStudio • Software Engineer • R Markdown Team


2 / 37
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
oTile View: Overview of Slides
Esc Back to slideshow