Format text

Columns of text in a data table will generally not be rendered in the same typeface as produced by format_numbers(). The format_text() function provides an approach to assigning a matching typeface to such columns.

Packages.   If you are writing your own script to follow along, we use the following packages in this vignette. Data frame operations are performed with data.table syntax. Some users may wish to translate the examples to use base R or dplyr syntax.



We format values as inline math expressions delimited by $ ... $ or the optional \( ... \). Inside the math delimiters, the text is formatted using math-text macros such as \mathrm, \mathit, etc.

For example, the text “Hello world!” is marked up as follows, where the space between words is preserved by a horizontal space macro (\>),


and is rendered in an R markdown document as: \(\small\mathrm{Hello\>world!}\). To program the markup, however, we enclose the markup in quote marks as a character string, that is,


where extra backslashes are necessary to “escape” the backslashes in \mathrm and \>. When the optional font size argument is assigned, formatdown adds a LaTeX-style sizing macro such as \small or \large, for example,


where again the markup includes an extra backslash.


Converts a character vector (or a vector coercible to character class) to math-text of the form,


where txt is the text to be formatted and \\math** is a font face macro such as \\mathrm, \\mathit, etc.


            face = "plain",
            size = formatdown_options("size"),
            delim = formatdown_options("delim"),
            whitespace = formatdown_options("whitespace"))

Examples.   These examples are shown with default arguments. Arguments are explored more fully starting with the next section.

# 1. One string
x <- "Alum 6061"
#> [1] "$\\mathrm{Alum\\>6061}$"

# 2. String vector
y <- c("Alum 6061", "Carbon steel", "Ni-Cr-Fe alloy")
#> [1] "$\\mathrm{Alum\\>6061}$"      "$\\mathrm{Carbon\\>steel}$"  
#> [3] "$\\mathrm{Ni-Cr-Fe\\>alloy}$"

Examples 1 and 2 (in inline code chunks) render as,

  1. \(\small \mathrm{Alum\>6061}\)
  2. \(\small \mathrm{Alum\>6061}\), \(\small \mathrm{Carbon\>steel}\), \(\small \mathrm{Ni-Cr-Fe\>alloy}\)

Input coercible to character

Illustrating that variables of different classes are coerced to character if possible. Starting with character class,

# 3. Character class
x <- c("abc", "def", NA_character_)
#> [1] "$\\mathrm{abc}$" "$\\mathrm{def}$" "$\\mathrm{NA}$"

Example 3 renders as:   \(\small \mathrm{abc}\), \(\small \mathrm{def}\), \(\small \mathrm{NA}\).

# 4. Numeric class
x <- c(10, 3e-05, 4.56e+10)
#> [1] "$\\mathrm{10}$"       "$\\mathrm{3e-05}$"    "$\\mathrm{4.56e+10}$"

Example 4 renders as:   \(\small \mathrm{10}\), \(\small \mathrm{3e-05}\), \(\small \mathrm{4.56e+10}\).

# 5. Logical class
x <- TRUE
#> [1] "$\\mathrm{TRUE}$"

Example 5 renders as:   \(\small \mathrm{TRUE}\).

# 6. Complex class
x <- 2 + (0+3i)
#> [1] "$\\mathrm{2+3i}$"

Example 6 renders as:   \(\small \mathrm{2+3i}\).

# 7. Date class
x <- Sys.Date()
#> [1] "$\\mathrm{2024-05-07}$"

Example 7 renders as:   \(\small \mathrm{2024-05-07}\).

# 8 Factor class
x <- as.factor(c("low", "med", "high"))
#> [1] "$\\mathrm{low}$"  "$\\mathrm{med}$"  "$\\mathrm{high}$"

Example 8 renders as:   \(\small \mathrm{low}\), \(\small \mathrm{med}\), \(\small \mathrm{high}\).

# 9. NULL class
x <- NULL
#> character(0)

Example 9 renders as a zero-length character (no visible output rendered).


Format the same column of text using each of the five possible face arguments for comparison.

# 10. Compare available typefaces
x <- c("One day", "at a", "time.")
plain <- format_text(x, face = "plain", size = "small")
italic <- format_text(x, face = "italic", size = "small")
bold <- format_text(x, face = "bold", size = "small")
sans <- format_text(x, face = "sans", size = "small")
mono <- format_text(x, face = "mono", size = "small")
DT <- data.table(plain, italic, bold, sans, mono)
knitr::kable(DT, align = "l", caption = "Example 10.")
Example 10.
plain italic bold sans mono
\(\small \mathrm{One\>day}\) \(\small \mathit{One\>day}\) \(\small \mathbf{One\>day}\) \(\small \mathsf{One\>day}\) \(\small \mathtt{One\>day}\)
\(\small \mathrm{at\>a}\) \(\small \mathit{at\>a}\) \(\small \mathbf{at\>a}\) \(\small \mathsf{at\>a}\) \(\small \mathtt{at\>a}\)
\(\small \mathrm{time.}\) \(\small \mathit{time.}\) \(\small \mathbf{time.}\) \(\small \mathsf{time.}\) \(\small \mathtt{time.}\)

One may use the LaTeX-style macro instead of the shorthand argument option. For example,

# 11. Two equivalent values for argument
hello_text <- "Hello world!"
p <- format_text(hello_text, face = "plain")
q <- format_text(hello_text, face = "\\mathrm")

# Demonstrate equivalence
all.equal(p, q)
#> [1] TRUE

Example 11 renders as:

Special characters in math mode

The argument of format_text() is evaluated within a math-markup. Thus any math syntax in your text, such as an underscore “_” or caret “^”, are rendered in math mode, not verbatim. For example, the underscore creates a subscript and the caret creates a superscript,

# 12. Special characters NOT escaped
#> [1] "$\\mathrm{R_e}$"
#> [1] "$\\mathrm{m^3}$"

Example 12 renders as:

If we wanted to retain the underscore or caret as characters, we can try to escape the special character or use the LaTeX verbatim function,

# 13. Special characters escaped
#> [1] "$\\mathrm{R\\_e}$"
#> [1] "$\\mathrm{m\\verb+^+3}$"

Example 13 renders as:


Arguments assigned using formatdown_options() are described in the Global settings article.