library(tinytable)
options(tinytable_tt_digits = 3)
options(tinytable_theme_placement_latex_float = "H")
<- mtcars[1:4, 1:5] x
Formatting
Numbers, dates, strings, etc.
The tt()
function is minimalist; it’s inteded purpose is simply to draw nice tables. Users who want to format numbers, dates, strings, and other variables in different ways should process their data before supplying it to the tt()
table-drawing function. To do so, we can use the format_tt()
function supplied by the tinytable
.
In a very simple case—such as printing 2 significant digits of all numeric variables—we can use the digits
argument of tt()
:
<- data.frame(
dat w = c(143002.2092, 201399.181, 100188.3883),
x = c(1.43402, 201.399, 0.134588),
y = as.Date(sample(1:1000, 3), origin = "1970-01-01"),
z = c(TRUE, TRUE, FALSE))
tt(dat, digits = 2)
w | x | y | z |
---|---|---|---|
143002 | 1.43 | 1971-02-15 | True |
201399 | 201.4 | 1970-10-29 | True |
100188 | 0.13 | 1971-08-15 | False |
We can get more fine-grained control over formatting by calling format_tt()
after tt()
, optionally by specifying the columns to format with j
:
tt(dat) |>
format_tt(
j = 2:4,
digits = 1,
date = "%B %d %Y") |>
format_tt(
j = 1,
digits = 2,
num_mark_big = " ",
num_mark_dec = ",",
num_zero = TRUE,
num_fmt = "decimal")
w | x | y | z |
---|---|---|---|
143 002,21 | 1.4 | February 15 1971 | True |
201 399,18 | 201.4 | October 29 1970 | True |
100 188,39 | 0.1 | August 15 1971 | False |
We can use a regular expression in j
to select columns, and the ?sprintf
function to format strings, numbers, and to do string interpolation (similar to the glue
package, but using Base R
):
<- data.frame(
dat a = c("Burger", "Halloumi", "Tofu", "Beans"),
b = c(1.43202, 201.399, 0.146188, 0.0031),
c = c(98938272783457, 7288839482, 29111727, 93945))
tt(dat) |>
format_tt(j = "a", sprintf = "Food: %s") |>
format_tt(j = 2, digits = 1) |>
format_tt(j = "c", digits = 2, num_suffix = TRUE)
a | b | c |
---|---|---|
Food: Burger | 1.432 | 99T |
Food: Halloumi | 201.399 | 7.3B |
Food: Tofu | 0.146 | 29M |
Food: Beans | 0.003 | 94K |
Finally, if you like the format_tt()
interface, you can use it directly with numbers, vectors, or data frames:
format_tt(pi, digits = 1)
[1] "3"
format_tt(dat, digits = 1, num_suffix = TRUE)
a b c
1 Burger 1 99T
2 Halloumi 201 7B
3 Tofu 0.1 29M
4 Beans 0.003 94K
Significant digits and decimals
By default, format_tt()
formats numbers to ensure that the smallest value in a vector (column) has at least a certain number of significant digits. For example,
<- data.frame(x = c(0.000123456789, 12.4356789))
k tt(k, digits = 2)
x |
---|
0.00012 |
12.43568 |
We can alter this behavior to ensure to round significant digits on a per-cell basis, using the num_fmt
argument in format_tt()
:
tt(k) |> format_tt(digits = 2, num_fmt = "significant_cell")
x |
---|
0.00012 |
12 |
The numeric formatting options in format_tt()
can also be controlled using global options:
options("tinytable_tt_digits" = 2)
options("tinytable_format_num_fmt" = "significant_cell")
tt(k)
x |
---|
0.00012 |
12 |
Math
To insert LaTeX-style mathematical expressions in a tinytable
, we enclose the expression in dollar signs: $...$
. Note that you must double backslashes in mathematical expressions in R strings.
In LaTeX, expression enclosed between $$
will automatically rendered as a mathematical expression.
In HTML, users must first load the MathJax JavaScript library to render math. This can be done in two ways. First, one can use a global option. This will insert MathJax scripts alongside every table, which is convenient, but could enter in conflict with other scripts if the user (or notebook) has already inserted MathJax code:
options(tinytable_html_mathjax = TRUE)
Alternatively, users can load MathJax explicitly in their HTML file. In a Quarto notebook, this can be done by using a code chunk like this:
```{=html}
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<script>
MathJax = {
tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']]
},
svg: {
fontCache: 'global'
}
};
</script>
```
Then, we can do:
<- data.frame(Math = c(
dat "$x^2 + y^2 = z^2$",
"$\\frac{1}{2}$"
))tt(dat) |> style_tt(j = 1, align = "c")
Math |
---|
$x^2 + y^2 = z^2$ |
$\frac{1}{2}$ |
To avoid inserting $...$
in every cell manually, we can use the math
argument of format_tt()
:
options(tinytable_html_mathjax = TRUE)
<- data.frame("y^2 = e^x" = c(-2, -pi), check.names = FALSE)
dat
tt(dat, digits = 3) |> format_tt(math = TRUE)
$y^2 = e^x$ |
---|
$-2 $ |
$-3.14$ |
Replacement
Missing values can be replaced by a custom string using the replace
argument (default ""
):
<- data.frame(a = c(NA, 1, 2), b = c(3, NA, 5))
tab
tt(tab)
a | b |
---|---|
NA | 3 |
1 | NA |
2 | 5 |
tt(tab) |> format_tt()
a | b |
---|---|
3 | |
1 | |
2 | 5 |
tt(tab) |> format_tt(replace = "-")
a | b |
---|---|
- | 3 |
1 | - |
2 | 5 |
We can also specify multiple value replacements at once using a named list of vectors:
<- data.frame(x = 1:5, y = c(pi, NA, NaN, -Inf, Inf))
tmp <- list("-" = c(NA, NaN), "-∞" = -Inf, "∞" = Inf)
dict tt(tmp) |> format_tt(replace = dict, digits = 2)
x | y |
---|---|
1 | 3.1 |
2 | - |
3 | - |
4 | -∞ |
5 | ∞ |
Escape special characters
LaTeX and HTML use special characters to indicate strings which should be interpreted rather than displayed as text. For example, including underscores or dollar signs in LaTeX can cause compilation errors in some documents. To display those special characters, we need to substitute or escape them with backslashes, depending on the output format. The escape
argument of format_tt()
can be used to do this automatically:
<- data.frame(
dat "LaTeX" = c("Dollars $", "Percent %", "Underscore _"),
"HTML" = c("<br>", "<sup>4</sup>", "<emph>blah</emph>")
)
tt(dat) |> format_tt(escape = TRUE)
LaTeX | HTML |
---|---|
Dollars $ | <br> |
Percent % | <sup>4</sup> |
Underscore _ | <emph>blah</emph> |
When applied to a tt()
table, format_tt()
will determine the type of escaping to do automatically. When applied to a string or vector, we must specify the type of escaping to apply:
format_tt("_ Dollars $", escape = "latex")
[1] "\\_ Dollars \\$"
Markdown
Markdown can be rendered in cells by using the markdown
argument of the format_tt()
function (note: this requires installing the markdown
as an optional dependency).
<- data.frame( markdown = c(
dat "This is _italic_ text.",
"This sentence ends with a superscript.^2^")
)
tt(dat) |>
format_tt(j = 1, markdown = TRUE) |>
style_tt(j = 1, align = "c")
markdown |
---|
This is italic text. |
This sentence ends with a superscript.2 |
Markdown syntax can be particularly useful when formatting URLs in a table:
<- data.frame(
dat `Package (link)` = c(
"[`marginaleffects`](https://www.marginaleffects.com/)",
"[`modelsummary`](https://www.modelsummary.com/)",
"[`tinytable`](https://vincentarelbundock.github.io/tinytable/)",
"[`countrycode`](https://vincentarelbundock.github.io/countrycode/)",
"[`WDI`](https://vincentarelbundock.github.io/WDI/)",
"[`softbib`](https://vincentarelbundock.github.io/softbib/)",
"[`tinysnapshot`](https://vincentarelbundock.github.io/tinysnapshot/)",
"[`altdoc`](https://etiennebacher.github.io/altdoc/)",
"[`tinyplot`](https://grantmcdermott.com/tinyplot/)",
"[`parameters`](https://easystats.github.io/parameters/)",
"[`insight`](https://easystats.github.io/insight/)"
),Purpose = c(
"Interpreting statistical models",
"Data and model summaries",
"Draw beautiful tables easily",
"Convert country codes and names",
"Download data from the World Bank",
"Software bibliographies in R",
"Snapshots for unit tests using `tinytest`",
"Create documentation website for R packages",
"Extension of base R plot functions",
"Extract from model objects",
"Extract information from model objects"
),check.names = FALSE
)
tt(dat) |> format_tt(j = 1, markdown = TRUE)
Package (link) | Purpose |
---|---|
marginaleffects |
Interpreting statistical models |
modelsummary |
Data and model summaries |
tinytable |
Draw beautiful tables easily |
countrycode |
Convert country codes and names |
WDI |
Download data from the World Bank |
softbib |
Software bibliographies in R |
tinysnapshot |
Snapshots for unit tests using `tinytest` |
altdoc |
Create documentation website for R packages |
tinyplot |
Extension of base R plot functions |
parameters |
Extract from model objects |
insight |
Extract information from model objects |
Custom functions
On top of the built-in features of format_tt
, a custom formatting function can be specified via the fn
argument. The fn
argument takes a function that accepts a single vector and returns a string (or something that coerces to a string like a number).
tt(x) |>
format_tt(j = "mpg", fn = function(x) paste(x, "mi/gal")) |>
format_tt(j = "drat", fn = \(x) signif(x, 2))
mpg | cyl | disp | hp | drat |
---|---|---|---|---|
21 mi/gal | 6 | 160 | 110 | 3.9 |
21 mi/gal | 6 | 160 | 110 | 3.9 |
22.8 mi/gal | 4 | 108 | 93 | 3.8 |
21.4 mi/gal | 6 | 258 | 110 | 3.1 |
For example, the scales
package which is used internally by ggplot2
provides a bunch of useful tools for formatting (e.g. dates, numbers, percents, logs, currencies, etc.). The label_*()
functions can be passed to the fn
argument.
Note that we call format_tt(escape = TRUE)
at the end of the pipeline because the column names and cells include characters that need to be escaped in LaTeX: _
, %
, and $
. This last call is superfluous in HTML.
<- data.frame(
thumbdrives date_lookup = as.Date(c("2024-01-15", "2024-01-18", "2024-01-14", "2024-01-16")),
price = c(18.49, 19.99, 24.99, 24.99),
price_rank = c(1, 2, 3, 3),
memory = c(16e9, 12e9, 10e9, 8e9),
speed_benchmark = c(0.6, 0.73, 0.82, 0.99)
)
tt(thumbdrives) |>
format_tt(j = 1, fn = scales::label_date("%e %b", locale = "fr")) |>
format_tt(j = 2, fn = scales::label_currency()) |>
format_tt(j = 3, fn = scales::label_ordinal()) |>
format_tt(j = 4, fn = scales::label_bytes()) |>
format_tt(j = 5, fn = scales::label_percent()) |>
format_tt(escape = TRUE)
date_lookup | price | price_rank | memory | speed_benchmark |
---|---|---|---|---|
2024-01-15 | $18.49 | 1 | 16000000000 | 60% |
2024-01-18 | $19.99 | 2 | 12000000000 | 73% |
2024-01-14 | $24.99 | 3 | 10000000000 | 82% |
2024-01-16 | $24.99 | 3 | 8000000000 | 99% |
Quarto data processing
Quarto automatically applies some data processing to the content of the tables it renders. By default, tinytable
disables this processing, because it can enter in conflict with styling and formatting features of the package.
To enable Quarto data processing, we can use the quarto
argument of the format_tt()
function. This argument allows users to mark certain cells explicitly for processing by Quarto, by wrapping them in a special “span” called “data-qmd”, supported by Quarto:
<- data.frame(Thing = "qwerty", Citation = "@Lovelace1842")
k
tt(k) |> format_tt(quarto = TRUE)
Thing | Citation |
---|---|
qwerty | Lovelace (1842) |
Some users may want to apply Quarto data processing to all tables. This can be done with themes:
<- function(x) format_tt(x, quarto = TRUE)
theme_quarto options(tinytable_tt_theme = theme_quarto)
tt(k)
Thing | Citation |
---|---|
qwerty | Lovelace (1842) |
Back to normal:
options(tinytable_tt_theme = NULL)
Alternatively, users can set a global option to process all tables in Quarto, but they will then have to mark each cell with special content using format_tt(quarto)
:
options(tinytable_quarto_disable_processing = FALSE)
tt(x)
mpg | cyl | disp | hp | drat |
---|---|---|---|---|
21.0 | 6 | 160 | 110 | 3.90 |
21.0 | 6 | 160 | 110 | 3.90 |
22.8 | 4 | 108 | 93 | 3.85 |
21.4 | 6 | 258 | 110 | 3.08 |
Notice that Quarto is now processing the table, so we lose the default tinytable
theme and get the default striped Quarto look.
Back to normal:
options(tinytable_quarto_disable_processing = TRUE)