Literate programming with markdown and $\LaTeX$: Part 1

Introduction

$\LaTeX$ is a Turing complete langauge besides being one of the popular typesetting systems in action since a very long ago. $\LaTeX$ workflows are fully reproducible and extremely customizable, hence its popularity over WYSIWYG softwares.

This my first in a series of lessons about easing the workflow with $\LaTeX$. I do not expect an all encompassing content, even for something that sets forth the starting point. I could only hope that with passage of time the code and workflow does not break, and even if it does, it does so with audibility.

Since I mostly integrate my R workflows with $\LaTeX$ in Rmarkdown documents, and very rarely fully in the typetting system, this post will be meaningful when connected to pdf_document* rendering of rmarkdowns. One major thing one should heed before setting forth on literate programming with $\LaTeX$ and R is the role of intermediate engine – pandoc. It is a critical horse that hauls the conversion to pdf (or virtually any other document formats). Get this in GitHub.

Tip 1

Best rmarkdown pdf output rendering header would be, as of this moment:

output: 
  bookdown::pdf_document2:
    toc: yes
    toc_depth: 3
    keep_tex: yes

Tip 2

A typical $\LaTeX$ document header will contain following packages loaded at its preamble. Generally, use these $\LaTeX$ packages in conjunction with R package kableExtra.

Note, however, the order of package specification might have to be tweaked. Anyway, if reordering has to be done (in case of package/option clash), always compile from the intermediate .tex file to cut short the time/resource to render output from rmd again.

header-includes:
- \usepackage{booktabs}
- \usepackage{longtable}
- \usepackage{array}
- \usepackage{multirow}
- \usepackage[table]{xcolor}
- \usepackage{wrapfig}
- \usepackage{float}
- \usepackage{colortbl}
- \usepackage{pdflscape}
- \usepackage{tabu}
- \usepackage{threeparttable}
- \usepackage[normalem]{ulem}
- \usepackage{xcolor}
- \usepackage{rotating}
- \newcommand{\blandscape}{\begin{landscape}}
- \newcommand{\elandscape}{\end{landscape}}
- \usepackage{subfig}
- \usepackage[format=hang,labelfont=bf,margin=0.5cm,justification=centering]{caption}

The assignment of \blandscape and \elandscape allows specification of landscape version of a page wherever desired within markdown body. However, pdflscape is a more advanced package that allows for change as well as automatic display of orientation in the document.

Tip 3

To specify current system’s date in output use following in yaml header.

date: "`r Sys.Date()`"

Tip 4

A setup code chunk will mostly find its place at the uppermost chunk position, usually after yaml header. It usually consists of the following.

library(tidyverse)
knitr::opts_chunk$set(tidy = TRUE, cache = TRUE, 
                      echo = FALSE, 
                      tidy.opts = list(width.cutoff=50), 
                      eval = TRUE, warning = FALSE, message = FALSE,
                      fig.align = "center", fig.width = 5,
                      fig.asp = 0.9, out.width = "0.7\\linewidth")
options(knitr.kable.NA = "", digits = 3, knitr.table.format = "latex")

Tip 5

For the tip mentioned in Tip 2, there is now a recommended way of loading $\LaTeX$ packages: Setting yet another setup options’ argument:

options(kableExtra.latex.load_packages = TRUE) # this is the default

Tip 6

Don’t forget to check on the booktabs in your table. With this, some other useful features of a kable() are:

kable(df, format = "latex", 
      caption = "This is a dataframe table", 
      digits = 3, booktabs = TRUE,
      align = 'l') %>% 
  kableExtra::kable_styling(latex_options = c("striped", 
                                              "hold_position", "scale_down"), 
                            full_width = FALSE, font_size = 11, position = "center")

Tip 7

  • Make use of kableExtra function landscape() to lay table in landscape orientation.
  • Make use of kable() function with argument longtable = TRUE to get enable page breaks in table.
  • Note that above two options are mutually exclusive.

Tip 8

How to getting really long and wide tables done.

  • Use pdf_document2 output format
  • Change geometry of output document in yaml header, with as simple as
geometry: "left=.85cm,right=0.85cm,top=1.5cm,bottom=1.0cm"
  • Change \tabcolsep in yaml header in header-includes option
  - \setlength{\tabcolsep}{1pt}
  • Use landscape orientation.
    • Method 1: To manually specify breakpoint somewhere in the markdown body, using landscape command:
    • Method 2: Use kableExtra::landscape() in the table. But be warned that it does not work with longtable=TRUE environment.
  - \newcommand{\blandscape}{\begin{landscape}}
  - \newcommand{\elandscape}{\end{landscape}}
  • Load a few extra \LaTeX packages in the header:
  - \usepackage{dcolumn}
  - \usepackage{tabularx}
  • Lower down the text font_size in kableExtra::kable_styling
  • Use options for column width specification and header row rotation. Additionally, enable borders_* and set alignment to increase legibility.
kableExtra::kable_styling(..., latex_options = c("striped", "hold_position", "repeat_header"))
kableExtra::column_spec(..., 3:ncol(df), "3.8em", border_left = T)
kableExtra::row_spec(..., 0, bold = TRUE, font_size = 8, angle = 45)
knitr::kable(..., align = paste0(rep("l", times = ncol(df)))) # don't collapse while working with kable
comments powered by Disqus

Related