TITLE: siunitx 'S' table column 'table-format' option DATE: 2021-08-01 AUTHOR: John L. Godlee ==================================================================== I can't believe it's taken me this long to figure out how to use the table-format option of the S column type from the siunitx package in a LaTeX table! A basic table in LaTeX, showing part of the mtcars dataset in R: \begin{table}[h] \centering \begin{tabular}{lrrrrr} \hline & {mpg} & {cyl} & {disp} & {drat} & {qsec} \\ \hline Mazda RX4 & 21 & 6 & 160 & 3.9 & 16.46 \\ Mazda RX4 Wag & 21 & 6 & 160 & 3.9 & 17.02 \\ Datsun 71 & 22.8 & 4 & 108 & 3.85 & 18.61 \\ Hornet 4 Drive & 21.4 & 6 & 258 & 3.08 & 19.44 \\ Hornet Sportabout & 18.7 & 8 & 360 & 3.15 & 17.02 \\ Valiant & 18.1 & 6 & 225 & 2.76 & 20.22 \\ \hline \end{tabular} \end{table} ![A basic table](https://johngodlee.xyz/img_full/sitable/basic.png) It's nice to align numeric columns by decimal point, which can be achieved using the S column type: \begin{tabular}{lSSSSS} But now the columns are all off centre: ![Table with misaligned 'S' columns](https://johngodlee.xyz/img_full/sitable/s_bad.png) It turns out, that the table-format option can be used to tell siunitx how many digits to expect both before and after the decimal point: \begin{tabular}{l S[table-format=2.1] S[table-format=1.0] S[table-format=3.0] S[table-format=1.2] S[table-format=2.2]} ![Table with properly aligned 'S' columns](https://johngodlee.xyz/img_full/sitable/s_good.png) I had always assumed that table-format referred to a version number, v3.2 for example, and not knowing what the differences were I had avoided using the option altogether. As an addendum, while I was figuring this out I also did some experiments in exporting nice looking LaTeX tables directly from R using the xtable package. Here is a basic xtable export snippet, the resulting table, and the table rendered by LaTeX: # Packages library(xtable) # Data data(mtcars) dat <- head(mtcars)[,c(1,2,3,5,7)] # Basic xtable, no formatting xtab_bad <- xtable(dat) # Write basic xtable to file fileConn <- file("xtab_bad.tex") writeLines(print(xtab_bad), fileConn) close(fileConn) % latex table generated in R 4.1.0 by xtable 1.8-4 package % Mon Aug 2 08:50:05 2021 \begin{table}[ht] \centering \begin{tabular}{rrrrrr} \hline & mpg & cyl & disp & drat & qsec \\ \hline Mazda RX4 & 21.00 & 6.00 & 160.00 & 3.90 & 16.46 \\ Mazda RX4 Wag & 21.00 & 6.00 & 160.00 & 3.90 & 17.02 \\ Datsun 710 & 22.80 & 4.00 & 108.00 & 3.85 & 18.61 \\ Hornet 4 Drive & 21.40 & 6.00 & 258.00 & 3.08 & 19.44 \\ Hornet Sportabout & 18.70 & 8.00 & 360.00 & 3.15 & 17.02 \\ Valiant & 18.10 & 6.00 & 225.00 & 2.76 & 20.22 \\ \hline \end{tabular} \end{table} ![standard xtable table output](https://johngodlee.xyz/img_full/sitable/xtab_bad.png) By default, xtable renders all columns as right-aligned, with two decimal places after columns identified as numeric, with no caption or label. Below is an improved table, created by adding some customisations to xtable: xtab_good <- xtable(dat, label = "table_a", align = c("l", "S[table-format=2.1]", "S[table-format=1.0]", "S[table-format=3.0]", "S[table-format=1.2]", "S[table-format=2.2]"), display = c("s", "f", "d", "d", "f", "f"), digits = c( 0, 1, 0, 0, 2, 2), caption = c("Test caption, this is the full caption.", "Testing short")) colSanit <- function(x){ paste0("{", x, "}") } rowSanit <- function(x){ paste0("{\\emph{", x, "}}") } # Write better xtable to file fileConn <- file("xtab_good.tex") writeLines(print(xtab_good, include.rownames = TRUE, caption.placement = "top", table.placement = "", booktabs = TRUE, sanitize.colnames.function = colSanit, sanitize.rownames.function = rowSanit, sanitize.text.function = function(x) {x}), fileConn) close(fileConn) % latex table generated in R 4.1.0 by xtable 1.8-4 package % Mon Aug 2 08:53:54 2021 \begin{table} \centering \caption[Test caption, this is the full caption.]{Testing short} \label{table_a} \begin{tabular}{lS[table-format=2.1]S[table-format=1.0]S[table-forma t=3.0]S[table-format=1.2]S[table-format=2.2]} \toprule & {mpg} & {cyl} & {disp} & {drat} & {qsec} \\ \midrule {\emph{Mazda RX4}} & 21.0 & 6 & 160 & 3.90 & 16.46 \\ {\emph{Mazda RX4 Wag}} & 21.0 & 6 & 160 & 3.90 & 17.02 \\ {\emph{Datsun 710}} & 22.8 & 4 & 108 & 3.85 & 18.61 \\ {\emph{Hornet 4 Drive}} & 21.4 & 6 & 258 & 3.08 & 19.44 \\ {\emph{Hornet Sportabout}} & 18.7 & 8 & 360 & 3.15 & 17.02 \\ {\emph{Valiant}} & 18.1 & 6 & 225 & 2.76 & 20.22 \\ \bottomrule \end{tabular} \end{table} ![A better xtable](https://johngodlee.xyz/img_full/sitable/xtab_good.png) The changes made: - Adds a label - label = - Aligns each column differently with S columns - align = - Enforces column content type - display = - Rounds digits in numeric columns - digits = - Adds both a short caption for the list of tables and a long caption for in the text - caption = - Defines functions to sanitize both the column names and the row names - colSanit(), rowSanit() - Includes the rownames - include.rownames = - Puts the caption above the table, which should be standard behaviour in my opinion - caption.placement = - Removes any table position forcing, better to do this in LaTeX - table.placement = - Uses booktabs to add toprule, midrule, bottomrule - booktabs =