3  Base Plots

3.1 LaTeX Expressions

I want to display LaTeX equations as the names on one of the axis, using basic plot. I will do this using the TeX() function from {latex2exp}.

Let us generate some dummy data:

library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
n <- 100
tb <- tibble(
  class = rep(
    c("Model 1 with $X \\sim N(0,1)$",
      "Model 2 with $X \\sim N(1,1)$"),
    each = n
  ),
  y = c(
    rnorm(n = n, mean = 0, sd = 1),
    rnorm(n = n, mean = 1, sd = 1)
  )
) |> 
  mutate(
    class = factor(class)
  )
tb
# A tibble: 200 × 2
   class                                 y
   <fct>                             <dbl>
 1 "Model 1 with $X \\sim N(0,1)$" -0.652 
 2 "Model 1 with $X \\sim N(0,1)$" -1.02  
 3 "Model 1 with $X \\sim N(0,1)$"  0.338 
 4 "Model 1 with $X \\sim N(0,1)$"  0.384 
 5 "Model 1 with $X \\sim N(0,1)$" -0.424 
 6 "Model 1 with $X \\sim N(0,1)$" -0.399 
 7 "Model 1 with $X \\sim N(0,1)$"  0.803 
 8 "Model 1 with $X \\sim N(0,1)$" -1.21  
 9 "Model 1 with $X \\sim N(0,1)$"  0.0629
10 "Model 1 with $X \\sim N(0,1)$" -0.891 
# ℹ 190 more rows

The levels:

lvls <- levels(tb$class)
lvls
[1] "Model 1 with $X \\sim N(0,1)$" "Model 2 with $X \\sim N(1,1)$"
par(mar = c(2.1, 10.1, 2.1, 2.1))
boxplot(
  y ~ class,
  data = tb,
  horizontal = TRUE,
  las = 1,
  xlab = NULL, ylab = NULL,
  yaxt = "n"
)


# Setting the y axis (with the LaTeX expressions)
axis(
  2, 
  at = 1:length(lvls), 
  labels = c(latex2exp::TeX(lvls)),
  las = 2
)

Note

Unfortunately, the \mathcal{} is not supported by R.

Now, what if we want to add a new line to the labels? It becomes a bit ugly…

tb <- tibble(
  class = rep(
    c(
      "$\\overset{\\normalsize{Model~1~with}}{X \\sim N(0,1)}$",
      "$\\overset{\\normalsize{Model~2~with}}{X \\sim N(1,1)}$"
    ),
    each = n
  ),
  y = c(
    rnorm(n = n, mean = 0, sd = 1),
    rnorm(n = n, mean = 1, sd = 1)
  )
) |> 
  mutate(
    class = factor(class)
  )
lvls <- levels(tb$class)

par(mar = c(2.1, 7.1, 2.1, 2.1))
boxplot(
  y ~ class,
  data = tb,
  horizontal = TRUE,
  las = 1,
  xlab = NULL, ylab = NULL,
  yaxt = "n"
)
# Setting the y axis (with the LaTeX expressions)
axis(
  2, 
  at = 1:length(lvls), 
  labels = c(latex2exp::TeX(lvls)),
  las = 2
)

3.2 Coloured LaTeX Expressions and Tikz

Assume we want to put a part of an equation using a user-defined colour in a plot that will be exported as a tikz picture which will then be executed with PDFLaTeX. To do so, the colour needs to be defined twice:

  1. When exporting the tikz picture, passed on to the packages argument of the tikz() function from {tikzDevice}.
  2. When creating the standalone document that will contain the tikz picture.
library(tikzDevice)

First, define colours in a TeX format. We equip them with useful commands; assume the colour defined is named ColourName, so that the following commands will be created:

  1. \grasColourName: bold and coloured text,
  2. \grasColourNameMath: coloured text in a math environment,
  3. \highlightColourName: coloured box around the coloured text,
  4. \highlightColourNameMath: coloured box around the coloured elements in a math formula (manually add \displaystyle if you are writing sums or integrals, if needed)
colours_tex <- paste0(
  c(
    "\\definecolor{wongBlack}{RGB}{0,0,0}",
    "\\definecolor{wongGold}{RGB}{230, 159, 0}",
    "\\definecolor{wongLightBlue}{RGB}{86, 180, 233}",
    "\\definecolor{wongGreen}{RGB}{0, 158, 115}",
    "\\definecolor{wongYellow}{RGB}{240, 228, 66}",
    "\\definecolor{wongBlue}{RGB}{0, 114, 178}",
    "\\definecolor{wongOrange}{RGB}{213, 94, 0}",
    "\\definecolor{wongPurple}{RGB}{204, 121, 167}",
    "\\definecolor{bleuTOL}{HTML}{332288}",
    "\\definecolor{vertTOL}{HTML}{117733}",
    "\\definecolor{vertClairTOL}{HTML}{44AA99}",
    "\\definecolor{bleuClairTOL}{HTML}{88CCEE}",
    "\\definecolor{sableTOL}{HTML}{DDCC77}",
    "\\definecolor{parmeTOL}{HTML}{CC6677}",
    "\\definecolor{magentaTOL}{HTML}{AA4499}",
    "\\definecolor{roseTOL}{HTML}{882255}",
    "\\definecolor{amuPrimeBlue}{RGB}{30, 100, 222}",
    "\\definecolor{amuPrimeYellow}{RGB}{255, 255, 133}",
    "\\definecolor{amuPrimeWhite}{RGB}{255, 255, 255}",
    "\\definecolor{amuPrimeBlack}{RGB}{0, 0, 0}",
    "\\definecolor{amuSecondOr}{HTML}{FED100}",
    "\\definecolor{amuSecondCorail}{HTML}{FF8B7C}",
    "\\definecolor{amuSecondOrange}{HTML}{FF7900}",
    "\\definecolor{amuSecondBleu}{HTML}{33CCFF}",
    "\\definecolor{amuSecondVert}{HTML}{53DE94}",
    "\\definecolor{amuSecondMauve}{HTML}{9966ff}",
    "\\definecolor{amuSecondOr}{HTML}{FED100}",
    "\\definecolor{amuSecondCorail}{HTML}{FF8B7C}",
    "\\definecolor{amuSecondOrange}{HTML}{FF7900}",
    "\\definecolor{amuSecondBleu}{HTML}{33CCFF}",
    "\\definecolor{amuSecondVert}{HTML}{53DE94}",
    "\\definecolor{amuSecondMauve}{HTML}{9966ff}",
    "\\definecolor{amuTerJaune}{HTML}{FFFFBF}",
    "\\definecolor{amuTerOcre}{HTML}{B2861B}",
    "\\definecolor{amuTerCorail}{HTML}{FFD4CC}",
    "\\definecolor{amuTerRouge}{HTML}{990000}",
    "\\definecolor{amuTerOrange}{HTML}{FFDEBF}",
    "\\definecolor{amuTerBrique}{HTML}{B25600}",
    "\\definecolor{amuTerBleuClair}{HTML}{CDEAFC}",
    "\\definecolor{amuTerBleuRoi}{HTML}{00008E}",
    "\\definecolor{amuTerVertClair}{HTML}{CAFEE4}",
    "\\definecolor{amuTerVertEmeraude}{HTML}{009A74}",
    "\\definecolor{amuTerLavande}{HTML}{DDCCFF}",
    "\\definecolor{amuTerViolet}{HTML}{660099}"
  ), 
  collapse = "\n"
)
  
macro_colours <- paste0(
  c(
    "\\usepackage[most]{tcolorbox}",
    "% ------------------------------------------------",
    "% Macro pour créer des commandes:",
    "% \\grasNomCouleur",
    "% \\grasNomCouleurMath",
    "% \\highlightNomCouleur",
    "% \\highlightNomCouleurMath",
    "% ------------------------------------------------",
    "% Base highlight macro (text-mode box)",
    "\\newcommand{\\highlight}[2]{\\colorbox{#1!17}{#2}}",
    "\\makeatletter",
    "\\newcommand{\\DefineColorCommands}[1]{%",
    "  % \\gras<Name> (text)",
    "  \\expandafter\\newcommand\\csname gras#1\\endcsname[1]{%",
    "    \\textbf{\\textcolor{#1}{##1}}%",
    "  }%",
    "  % \\highlight<Name> (text)",
    "  \\expandafter\\newcommand\\csname highlight#1\\endcsname[1]{%",
    "    \\highlight{#1}{\\csname gras#1\\endcsname{##1}}%",
    "  }%",
    "  % \\gras<Name>Math (math)",
    "  \\expandafter\\newcommand\\csname gras#1Math\\endcsname[1]{%",
    "    {\\color{#1}##1}%",
    "  }%",
    "  % \\highlight<Name>Math (works in text AND math; no nested $)",
    "  \\expandafter\\newcommand\\csname highlight#1Math\\endcsname[1]{%",
    "    \\highlight{#1}{\\ensuremath{\\csname gras#1Math\\endcsname{##1}}}%",
    "  }%",
    "}",
    "\\makeatother\n"
  ),
  collapse = "\n"
)
  
macro_color_def <- paste0(
  c(
    "\\DefineColorCommands{wongBlack}",
    "\\DefineColorCommands{wongGold}",
    "\\DefineColorCommands{wongLightBlue}",
    "\\DefineColorCommands{wongGreen}",
    "\\DefineColorCommands{wongYellow}",
    "\\DefineColorCommands{wongBlue}",
    "\\DefineColorCommands{wongOrange}",
    "\\DefineColorCommands{wongPurple}",
    "\\DefineColorCommands{bleuTOL}",
    "\\DefineColorCommands{vertTOL}",
    "\\DefineColorCommands{vertClairTOL}",
    "\\DefineColorCommands{bleuClairTOL}",
    "\\DefineColorCommands{sableTOL}",
    "\\DefineColorCommands{parmeTOL}",
    "\\DefineColorCommands{magentaTOL}",
    "\\DefineColorCommands{roseTOL}",
    "\\DefineColorCommands{amuPrimeBlue}",
    "\\DefineColorCommands{amuPrimeYellow}",
    "\\DefineColorCommands{amuPrimeWhite}",
    "\\DefineColorCommands{amuPrimeBlack}",
    "\\DefineColorCommands{amuSecondOr}",
    "\\DefineColorCommands{amuSecondCorail}",
    "\\DefineColorCommands{amuSecondOrange}",
    "\\DefineColorCommands{amuSecondBleu}",
    "\\DefineColorCommands{amuSecondVert}",
    "\\DefineColorCommands{amuSecondMauve}",
    "\\DefineColorCommands{amuTerJaune}",
    "\\DefineColorCommands{amuTerOcre}",
    "\\DefineColorCommands{amuTerCorail}",
    "\\DefineColorCommands{amuTerRouge}",
    "\\DefineColorCommands{amuTerOrange}",
    "\\DefineColorCommands{amuTerBrique}",
    "\\DefineColorCommands{amuTerBleuClair}",
    "\\DefineColorCommands{amuTerBleuRoi}",
    "\\DefineColorCommands{amuTerVertClair}",
    "\\DefineColorCommands{amuTerVertEmeraude}",
    "\\DefineColorCommands{amuTerLavande}",
    "\\DefineColorCommands{amuTerViolet}"
  ),
  collapse = "\n"
)

The standalone document that will contain the tikz picture can be created with the following function, plot_to_pdf().

#' From plot created with {tikzDevice}, create a standalone latex document
#' and compile it with pdflatex to save the plot as pdf
#'
#' @param filename Name of the tex file (WITHOUT THE EXTENSION) that contains
#'  the tikzpicture.
#' @param path_to_latex Path to LaTeX engine (Defaults to
#'   `/Library/TeX/texbin/`).
#' @param interpreter By default, use pdflatex (`pdflatex`).
#' @param path Path to the destination folder.
#' @param keep_tex should the tex file (only the one from the standalone doc)
#'  be kept after compilation? Defaults to `FALSE`.
#' @param verbose A logical value indicating whether diagnostic messages are
#'   printed when measuring dimensions of strings. Defaults to `FALSE`.
#' @param ignore.stdout A logical (not NA) indicating whether messages written
#'   to ‘stdout’  should be ignored. Defaults to `TRUE`.
#' @param crop If `TRUE` (default to `FALSE`), the PDF is cropped using pdfcrop.
#'
plot_to_pdf <- function(filename,
                        path_to_latex = "/Library/TeX/texbin/",
                        interpreter = "pdflatex",
                        path = "./",
                        additional_tex_header = "",
                        keep_tex = FALSE,
                        verbose = FALSE,
                        ignore.stdout = TRUE,
                        crop = FALSE) {
  
  
  
  content <- paste0(
    "\\documentclass{standalone}
      \\usepackage{amsmath,amssymb}
      \\usepackage{graphicx}
      \\usepackage{array,dcolumn}
      \\usepackage[T1]{fontenc}
      \\usepackage[utf8]{inputenc}
      \\usepackage{nicefrac}
      \\usepackage{pgfplots}
      \\usetikzlibrary{pgfplots.groupplots}
      \\usepackage{xcolor}",
    paste0(additional_tex_header, collapse = "\n"),
    "\\begin{document}

      \\input{",
    path, filename,
    ".tex}

      \\end{document}"
  )
  
  # The file which will import the graph in tex format
  fileConn <- file(paste0(path, filename, "_tmp.tex"))
  writeLines(content, fileConn)
  close(fileConn)
  
  # Process tex file to get the PDF
  system(
    paste0(
      path_to_latex,
      interpreter, " -shell-escape -synctex=1 -interaction=nonstopmode  ",
      path,
      filename, "_tmp.tex"),
    ignore.stdout = TRUE
  )
  if (crop == TRUE) {
    system(
      paste0(
        "pdfcrop ", filename, "_tmp.pdf ", filename, "_tmp.pdf"
      )
    )
  }
  if(!path %in%  c(".", "./", "/"))
    system(paste0("mv ", filename, "_tmp.pdf ", path))
  system(paste0("rm ", filename, "_tmp.aux"))
  system(paste0("rm ", filename, "_tmp.log"))
  system(paste0("rm ", filename, "_tmp.synctex.gz"))
  if (!keep_tex) {
    system(paste0("rm ", path, filename, "_tmp.tex"))
  }
  system(paste0("mv ", path, filename, "_tmp.pdf ", path, filename, ".pdf"))
}

Create a graph where two elements will be coloured: a label on the x-axis, and a formula on the graph.

# Parameters of the Gaussian distribution
mu    <- 0
sigma <- 1
# Grid
x <- seq(mu - 4 * sigma, mu + 4 * sigma, length.out = 800)
# Density
fx <- dnorm(x, mean = mu, sd = sigma)
par(mar = c(4, 4, 3, 1))


# Figure dimension
width_fig_tkz <- 5
height_fig_tkz <- 3
# Name of the file (without the extension), and path
file_name <- "pdf-gaussian"
path_figs <- "figs/"
if(!dir.exists(path_figs)) dir.create(path_figs)

tikz(
  paste0(path_figs, file_name, ".tex"),
  width = width_fig_tkz, height = height_fig_tkz,
  packages = c(
    getOption('tikzLatexPackages'), # do not forget to append the current options
    "\\usepackage{xcolor}",
    "\\usepackage{amsthm,amssymb,amsbsy,amsfonts,amscd,mathrsfs, mathtools}",
    "\\usepackage{amsmath}",
    colours_tex,
    macro_colours,
    macro_color_def
  )
)

plot(
  x, fx,
  type = "l",
  lwd  = 2,
  main = "Gaussian PDF",
  xlab = "$x$",
  ylab = "$f_X(x)$",
  axes = FALSE
)
axis(2)
axis(
  1, at = c(-4, -2, 0, 2, 4), 
  labels = c(-4, -2, "${\\color{wongBlue}\\mu}=0$", 2, 4)
)
text(x = -2, y = .3, "$\\highlightwongBlueMath{X\\sim\\mathcal{N}(0,1)}$")

dev.off()
quartz_off_screen 
                2 
# Applying our function to compile the tikz picture and outpout a PDF version
plot_to_pdf(
  filename = file_name, path = path_figs, 
  additional_tex_header = c(colours_tex, macro_colours, macro_color_def),
  keep_tex = FALSE, # remove the standalone tex document
  crop = TRUE
)

# Remove the file containing the tikz picture generated with tikz()
system(paste0("rm ", path_figs, file_name, ".tex"))
The exported PDF image