library(tabularray)
library(dplyr)
# helper to display the generated LaTeX in this vignette
show_latex <- function(x) cat(as.character(tblr_as_latex(x)))tabularray turns a data frame into LaTeX markup for the
tabularray LaTeX package.
Inspired by gt, you build a table
by piping a data frame into tblr() and then chaining
set_*() functions to add styling, before rendering with
tblr_as_latex().
A first table
tblr() initializes a data frame as a table object.
Printing it (or calling tblr_as_latex()) produces
LaTeX:
df <- tibble(
continent = c("Europe", "Asia", "Asia"),
country = c("Germany", "China", "Afghanistan"),
value = c(0.17, 0.23, 11.3)
)
df |> tblr() |> show_latex()\begin{center}
\begin{booktabs}{
colspec = {llr}
}
\toprule
continent & country & value \\
\midrule
Europe & Germany & 0.17 \\
Asia & China & 0.23 \\
Asia & Afghanistan & 11.30 \\
\bottomrule
\end{booktabs}
\end{center}
Numeric columns are right-aligned, text columns left-aligned. Column labels default to the column names.
Formatting
tabularray does not try to be a formatting toolkit. For
currency, percentages, thousands separators, significant digits, custom
date formats, or any other per-column formatting, format the column
before calling tblr() — for example with scales, base::format(),
base::formatC(), or base::sprintf():
tibble(
item = c("Widget", "Gadget"),
price = c(1999.5, 12.4),
added = as.Date(c("2024-01-15", "2024-11-03"))
) |>
mutate(
price = scales::dollar(price), # currency, via scales
added = format(added, "%B %d, %Y") # a custom date format, via base R
) |>
tblr() |>
show_latex()\begin{center}
\begin{booktabs}{
colspec = {lll}
}
\toprule
item & price & added \\
\midrule
Widget & \$1,999.50 & January 15, 2024 \\
Gadget & \$12.40 & November 03, 2024 \\
\bottomrule
\end{booktabs}
\end{center}
The formatted price is now a text column, so the literal
$ it contains is escaped to \$ for you — write
the plain character you want and let tblr handle the
escaping.
Columns you leave untouched are converted with sensible defaults: numbers get two decimal places (integer and whole-valued columns without), and dates, logicals, and other types are rendered as R would display them.
Escaping
Characters that are special in LaTeX (&,
%, $, _, #,
{, }, ~, ^,
\) are escaped automatically in text
columns, so ordinary data is safe:
\begin{center}
\begin{booktabs}{
colspec = {l}
}
\toprule
account \\
\midrule
R\&D \\
50\% off \\
a\_b \\
\bottomrule
\end{booktabs}
\end{center}
Two things to keep in mind:
Convert column types before
tblr(). Escaping is decided from each column’s type when the table is rendered. If you format a column upstream (as in the price example above), it is treated as text and escaped like any other text column.Labels, spanners, alignment, notes, and options are raw LaTeX. Values you pass to
set_column_labels(),set_column_spanner(),set_colspec(),set_source_notes(),set_interface(), andset_options()are inserted verbatim, so you can use LaTeX commands there — and you must escape any special characters yourself (e.g. writeR\&D, notR&D).
df |>
tblr() |>
set_column_labels(value = "\\textbf{Value}") |>
show_latex()\begin{center}
\begin{booktabs}{
colspec = {llr}
}
\toprule
continent & country & \textbf{Value} \\
\midrule
Europe & Germany & 0.17 \\
Asia & China & 0.23 \\
Asia & Afghanistan & 11.30 \\
\bottomrule
\end{booktabs}
\end{center}
Grouping, spanners, and themes
Group rows with dplyr::group_by() before
tblr(), add spanning headers with
set_column_spanner() (call it once per spanner row,
bottom-up), and tune the appearance with set_theme():
starwars |>
filter(homeworld == "Tatooine", !name %in% c("Anakin Skywalker", "Darth Vader")) |>
select(name, height, mass, sex, birth_year) |>
mutate(sex = stringr::str_to_title(sex)) |>
group_by(sex) |>
tblr(type = "float", caption = "Tatooine characters") |>
set_column_labels(name = "", birth_year = "Birth Year") |>
set_column_spanner(c(height, mass) ~ "Physical") |>
set_theme(row_group_style = "panel") |>
show_latex()\begin{center}
\begin{talltabs}[
caption = {Tatooine characters}
]{
colspec = {lrrr}
}
\toprule
& \SetCell[c=2]{c} Physical & & \\
\cmidrule{2-3}
& height & mass & Birth Year \\
\midrule
& \SetCell[c=3]{c} \textit{Male} & & \\
\cmidrule{2-4}
Luke Skywalker & 172 & 77 & 19 \\
Owen Lars & 178 & 120 & 52 \\
Biggs Darklighter & 183 & 84 & 24 \\
Cliegg Lars & 183 & NA & 82 \\
\addlinespace
& \SetCell[c=3]{c} \textit{None} & & \\
\cmidrule{2-4}
C-3PO & 167 & 75 & 112 \\
R5-D4 & 97 & 32 & NA \\
\addlinespace
& \SetCell[c=3]{c} \textit{Female} & & \\
\cmidrule{2-4}
Beru Whitesun Lars & 165 & 75 & 47 \\
Shmi Skywalker & 163 & NA & 72 \\
\bottomrule
\end{talltabs}
\end{center}
The type argument selects the LaTeX environment:
"simple" (default, inline), "float" (numbered,
captioned, supports notes), or "break" (page-breaking).
Using the output
The generated markup needs the tabularray package and
its booktabs library. In a LaTeX preamble:
A reasonably recent tabularray (2023 or later) is
recommended. In Quarto or R Markdown, the output is embedded verbatim —
see the README
for the YAML setup. You can also copy the LaTeX into any editor.
