How to create professional reports from R scripts, with custom styles.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.
Introduction
If the practical tips for R Markdown post we talked briefly about how we can easily create professional reports directly from R scripts, without the need for converting them manually to Rmd and creating code chunks. In this one, we will provide useful tips on advanced options for styling, using themes and producing light-weight HTML reports directly from R scripts. We will also provide a repository with example R script and rendering code to get different styled and sized outputs easily.
Contents
Creating reports directly from R scripts
For an introduction on creating nice reports directly from R scripts, look into the relevant section of the previous blog post. In one sentence, we can just call one of the following:
# with knitr directly knitr::spin("path-to-r-script.R") # or with rmarkdown rmakdown::render("path-to-r-script.R")
to create a report from an R script directly. Both spin()
and render()
provide a default style that will be used to render an R script to html. The same is true from RStudio’s built-in File -> Compile report...
functionality, which will call render()
in the background when used.
We might, however, be interested in using different styles other than the default one when rendering our R scripts into HTML reports, and there are multiple ways to achieve this.
Including styles the quick, dirty and risky way
The fastest way to include a custom css stored in a file is to simply include a line like the following at the beginning of the R script that we are using spin()
on:
'# <link rel="stylesheet" type="text/css" href="path-to-our.css">
This simple approach however has many caveats, as the line is just inserted into the body of the document within a paragraph, completely oblivious to what else was inserted. Unless there is a very good reason, we should use one of the safer and more robust approaches mentioned below.
Using knitr’s spin directly
Under the spin’s hood
Under the hood, spin()
calls knit2html()
, which passes many useful arguments to markdownToHTML()
, the function that actually converts a markdown file to the final HTML format. Unfortunately, many of those useful arguments are not exposed via spin()
.
Bearing this in mind, we have a few ways to access and provide them with the desired values:
- Changing the options that govern the default values and just call
spin()
as before - Perform the spinning in 2 steps
Changing the options that govern the default values and just call spin()
as before
As mentioned above, spin()
does not expose the arguments of markdownToHTML()
directly, so what happens in practice is that the default values for those arguments are used when spin()
is called. Some of the interesting arguments are by default selected in the following way:
options = getOption("markdown.HTML.options"), extensions = getOption("markdown.extensions") stylesheet = getOption("markdown.HTML.stylesheet") template = getOption("markdown.HTML.template")
Let’s have a look at some interesting default options’ values:
library(markdown) options()[c( "markdown.HTML.options", "markdown.extensions", "markdown.HTML.stylesheet" )] ## $markdown.HTML.options ## [1] "use_xhtml" "smartypants" "base64_images" "mathjax" ## [5] "highlight_code" ## ## $markdown.extensions ## [1] "no_intra_emphasis" "tables" "fenced_code" ## [4] "autolink" "strikethrough" "lax_spacing" ## [7] "space_headers" "superscript" "latex_math" ## ## $markdown.HTML.stylesheet ## [1] "/usr/local/lib/R/site-library/markdown/resources/markdown.css"
If we want to keep the spinning in one step, we can simply update those options before calling spin (and ideally change them back afterwards). For a somewhat minimalistic HTML output still keeping images self-contained, we can do:
options( markdown.extensions = "fenced_code", markdown.HTML.options = "base64_images", markdown.HTML.stylesheet = "{}" ) knitr::spin("spin_exaple.R")
To use a custom css stylesheet instead of the one provided by default with the markdown package:
options(markdown.HTML.stylesheet = "path_to_custom.css") knitr::spin("path-to-r-script.R")
Perform the report creation in 2 steps
The method above works but can seem quite workaround-ish. The method that could be considered more proper is to actually split the production of the final output into 2 steps:
- Generate an intermediate .Rmd file via
spin()
, usingspin(..., knit = FALSE)
- Run
knit2html()
on the created .Rmd file with the desired options directly specified as arguments
This allows us to provide additional arguments extensions
, stylesheet
, header
, template
and encoding
in the second step, instead of relying on the changed options to be passed as defaults.
The below example will embed styles present in path_to_custom.css
into the resulting HTML:
# Creates the intermediate path-to-r-script.Rmd knitr::spin("path-to-r-script.R", knit = FALSE) # Now create the final HTML output from # path-to-r-script.Rmd, with desired options knitr::knit2html( input = "path-to-r-script.Rmd", stylesheet = "path_to_custom.css" )
Using both of the above options will actually embed the css directly into the HTML output that is produced, making the output larger in size.
Note that the arguments we are looking to provide to knit2html()
are implemented as part of ...
, so we will have to name them. To look at the details, study the documentation of markdownToHTML()
, to which those arguments get passed.
Using rmarkdown’s render()
To produce an HTML report from an R script we can also use rmarkdown::render()
on an R script file. This will create a report with slight differences to the default knit()
output, one notable for HTML output is that render()
will by default include inline base64 representations of fonts and JavaScript sources. It will also include some potentially useful metadata, such as the author’s name and the date of rendering.
The output_format powerhouse
The output of render()
is governed mainly by the output_format
argument. Most of the time users will pass on just the name of the format, such as "html_document"
, as most of the options are governed by the yaml metadata present at the beginning of our Rmd files.
For R scripts we usually do not use the yaml metadata. In this case, we can take full advantage of the flexibility of that argument, passing a call to rmarkdown::html_document()
with the desired parameters as output_format
.
Minimalistic output with render()
To produce a minimalistic HTML output from our path-to-r-script.R
script, we can for example specify the following as output_format
:
rmarkdown::render( "path-to-r-script.R", output_format = rmarkdown::html_document( theme = NULL, mathjax = NULL, highlight = NULL ) )
Custom css with render()
Including a custom css stylesheet is equally simple, just provide a css
argument with the css file path to the html_document()
function:
rmarkdown::render( "path-to-r-script.R", output_format = rmarkdown::html_document( theme = NULL, mathjax = NULL, highlight = NULL, css = "path_to_custom.css" ) )
An interesting property of including custom css styles is that by default the argument self_contained
is set to TRUE
, meaning that the full stylesheet will be embedded into the output HTML file, including all the external css imported into the one we are using. This means that if your stylesheets import external fonts such as the following, those will also be pasted directly into the output:
@import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,300);
This behavior is different for spin()
, which will paste the @import
clause into the output as-is, instead of parsing and pasting the actual content of the provided url.
TL;DR: Just show me the examples
If instead of reading about it you would like to just test it yourself, I created a very simple R project showcasing the mentioned methods and some more available via a GitLab repo.
The project has the following files:
src/path-to-r-script.R
– an R script with custom formatted comments to be used as the source for creating reports withknitr::spin()
andrmarkdown::render()
rendering_render.R
– an R script that usesrmarkdown::render()
to create multiple different output reports based onpath-to-r-script.R
and save them tooutputs/
rendering_spin.R
– an R script that usesknitr::spin()
to create multiple different output reports based onpath-to-r-script.R
and save them tooutputs/
outputs/
– HTML reports generated from the content ofpath-to-r-script.R
by runningrendering_spin.R
andrendering_render.R
css/
– Example css used for creatingoutputs/ex_04_spin_air_css.html
, all credit for theair.css
goes to https://github.com/markdowncss/air
References
- HTML document chapter of the R Markdown: The Definitive Guide book
- Create R Markdown reports and presentations even better with these 3 practical tips
- air.css style used to create the report on the screenshot above
R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.