Skip to main content

Dynamic Latex Documents With R Components

· 4 min read
Quentin Faidide

Markdown and Latex combined with the R statistical scripting language are a popular solution to generate documents with figures. It can be a huge productivty booster to be able to both model and report at the same time.

Nonetheless it's likely one day that you will come across a situation where you will need to programatically generate cells of code. There is a recent feature in the knitr package that provides basic component templating that I will walk readers through in this tutorial.

warning

You might need to install the missing R and Latex packages that are used within this tutorial.

Introduction

We want to generate a document in Latex that will contain static content, with the figures generated from code sections in R.

We then want dynamic sections where the cells of code are templated from a component file.

You can also do it with Markdown

If you are used to making R Markdown documents instead, you can replace the latex code with markdown and give it the .Rmd file extension. This should allow you to template components in a similar fashion.

Root document template

Let's first create a root_document_template.rnw document that will be the base template for the Latex document part that is static. It can includes cells of codes that generate figures.

root_document_template.rnw
\documentclass[landscape, a4paper]{article}

\usepackage[sfdefault]{roboto}
\usepackage[T1]{fontenc}
\usepackage[english]{babel}
\usepackage{sectsty}
\usepackage{url}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{subfigure}
\usepackage{color}
\usepackage{placeins}
\usepackage{eso-pic}
\usepackage{afterpage}
\usepackage{anyfontsize}
\usepackage{setspace}
\usepackage{titlesec}
\usepackage{multicol}
\usepackage{enumitem}
\usepackage{wasysym}
\usepackage[table]{xcolor}
\usepackage{graphicx}
\usepackage{subcaption}

% recommended by kableExtra
\usepackage{float}
\usepackage{longtable}
\usepackage{array}
\usepackage{multirow}
\usepackage{booktabs}
\usepackage{wrapfig}
\usepackage{float}
\usepackage{colortbl}
\usepackage{pdflscape}
\usepackage{tabu}
\usepackage{threeparttable}
\usepackage{threeparttablex}
\usepackage[normalem]{ulem}
\usepackage{makecell}
%\usepackage{xcolor}

\usepackage{geometry}
\geometry{margin=0.6cm}
\setlength{\marginparwidth}{0px}
\setlength{\hoffset}{0px}
\setlength{\footskip}{0px}

\begin{document}
\selectlanguage{english}

\begin{multicols}{2}

{\noindent\fontsize{20}{40}\selectfont{My Report}}
\newline
\hspace{0.5cm}
{\noindent\fontsize{14}{20}\selectfont{Subtitle of my report}}

\columnbreak

\large
\begin{flushright}
{
\fontsize{14}{20}
{Written by \textbf{My Name}}

{\today}
}
\end{flushright}

\end{multicols}

\tableofcontents

% We can include libraries that would be used in components here%
<<echo=FALSE, cache=TRUE, warning=FALSE>>=
library(kableExtra)
@

\section{Introduction}

This document is a demonstration document for features of the R knit package.
It shows how to programatically generate documents, where the code defines
the content.

\section{Static Content}

This section contains a figure with a label.

\begin{center}
\begin{figure}[h]
\caption{This is a static figure with a numbered label at the top.}
<<echo=FALSE, cache=FALSE, warning=FALSE, fig.height=9, fig.width=10>>=
plot(1:10, 1:10, main="Static figure from root document")
@
\end{figure}
\end{center}

\section{Dynamic Content}

{{template_content}}

\end{document}

Note that this is not a regular Latex document, as it contains chunks of R code enclosed within delimiters. This latex document will then have a R session tied to it.

There are a few parameters for these R chunks that we are using:

  • The echo parameter decides whether or not the code from this cell will be shown before the output.
  • The cache parameter, when true, tells that this cells result should be cached and reuse unless the code changes. When false, it always execute the code to regenerate the content.
  • The warning parameter decides whether or not R warnings are shown.
  • The fig.height and fig.width parameters define the dimensions of the optional figures that this cell of code generates. Note that a larger width will lead your figure to be "zoomed out".

Latex Components

We now create a section_component.rnw file that defines our component for which we will dynamically generated instances we will later insert in the root document.

section_component.rnw

\newpage

\subsection{Section about {{component_subject}}}

\begin{center}
\begin{figure}[h]
\caption{Figure description {{component_subject}} }
<<echo=FALSE, cache=FALSE, warning=FALSE, message=FALSE, fig.height=9, fig.width=20>>=
plot({{component_multiplier}}*(1:10), 1:10, main="Dynamic figure about {{component_subject}}")
@
\end{figure}
\end{center}
\FloatBarrier

Generating the document

We will stack up code generated from this component one chunk after the other, and we will insert all that inside the root rnw document. Using the output rnw file, we will execute the R cells to obtain a tex document. Finally, we create a PDF using pdflatex.

The first steps are performed from the R scripting language:

library(knitr)

# defining the components data
components_data_df <- data.frame(
"subject"=c("Subject 1", "Subject 2", "Subject 3", "Subject 4", "Subject 5"),
"multiplier"=c(1, 2, 3, 4, 5)
)

# generating the raw content with multiple instances of the component
template_content <- NULL
for (i in seq_along(components_data_df)) {
component_multiplier <- components_data_df$multiplier[i]
component_subject <-components_data_df$subject[i]
template_content <- paste(template_content, knit_expand("section_component.rnw"), sep = "\n\n")
}

# inserting the dynamic content within the root document
template_result <- knit_expand("root_document_template.rnw")

# writing the rnw document to a file
write(template_result, "output_document.rnw")

# generating the latex and executing the R cells
knit("output_document.rnw")

Finally, an output_document.tex file should now live inside the current working directory, and we can make it a pdf with the following bash command:

pdflatex output_document.tex