Using table1 with \\LaTeX{} and MS Word

library(kableExtra, quietly=TRUE)
library(flextable, quietly=TRUE)
library(table1, quietly=TRUE)
try(detach('package:printr', unload = TRUE), silent=TRUE) # Make sure printr is not loaded

f <- function(x, n, ...) factor(sample(x, n, replace=TRUE, ...), levels=x)
set.seed(427)

n <- 146
dat <- data.frame(id=1:n)
dat$treat <- f(c("Placebo", "Treated"), n, prob=c(1, 2)) # 2:1 randomization
dat$age   <- sample(18:65, n, replace=TRUE)
dat$sex   <- f(c("Female", "Male"), n, prob=c(.6, .4))  # 60% female
dat$wt    <- round(exp(rnorm(n, log(70), 0.23)), 1)

# Add some missing data
dat$wt[sample.int(n, 5)] <- NA

label(dat$age)   <- "Age"
label(dat$sex)   <- "Sex"
label(dat$wt)    <- "Weight"
label(dat$treat) <- "Treatment Group"

units(dat$age)   <- "years"
units(dat$wt)    <- "kg"

Introduction

A long requested feature has been the ability to use table1 in rmarkdown documents that render to \LaTeX{} or .docx (i.e. Microsoft\textsuperscript{\textregistered} Word). Since version 1.4 of table1, this is now possible (with some limitations) by converting the output of table1() to a data.frame, kableExtra or flextable, using the functions as.data.frame(), t1kable() and t1flex() respectively, as these objects can be rendered to \LaTeX{} (note: data.frame (via pandoc) and flextable objects can also be rendered to .docx format, while, kableExtra cannot).

Examples

We demonstrate this using a familiar example from the main vignette. First, we can try the data.frame approach:

x <- table1(~ age + sex + wt | treat, data=dat)
as.data.frame(x)

By default, this does not produce a \LaTeX{} table, but the same text output you would see in the R console. If the printr package is loaded, however, we do get a \LaTeX{} table by default:

library(printr, quietly=TRUE)
as.data.frame(x)

Alternatively, we can use the knitr::kable() function:

kable(as.data.frame(x), booktabs=TRUE)

The output here is a bit nicer because we have specified the booktabs option, but because we are talking about a simple data.frame, there is no option to specify formatting (like bold text for variable labels, for instance).

Next, we can try the t1kable() function, to produce a kableExtra object:

t1kable(x)

This looks a bit better: it uses the booktabs option by default, and also has bold variable labels. But because of a limitation with multiline headers (i.e. headers that contain line breaks), the N=XX for each column is placed in the first row of the table, which is less than ideal.

Finally, we can try using the t1flex() function to produce a flextable object:

t1flex(x)

(Note that that flextable output, in particular the font, is different depending on whether the xelatex, lualatex or pdflatex engine is used, and flextable emits a warning when pdflatex, the default for rmarkdown documents, is used because xelatex and lualatex gives more font options.)

The output is less attractive in my opinion, and less consistent with the typical look of \LaTeX{} tables and documents. It is more spaced out, doesn't have bold labels or line break in the column headers (actually, this is a problem common to both packages, but the t1kable() and t1flex() functions deal with it differently because flextable will actually include the line breaks in HTML and .docx output, and the overall best approach is unclear), and doesn't use the booktabs package (the thickness of the horizontal rules is different). Also, flextable places the table in a float, whereas kableExtra leaves it inline. I personally would use kableExtra over flextable in a \LaTeX{} documents, and in fact I have made this the default output in a \LaTeX{} context (i.e., when using rmarkdown with a \LaTeX{} output format). But a big advantage of flextable is that in can render to .docx format (i.e. Microsoft Word), which kableExtra cannot, and is the default output in that context.

Nested groups

Nested groups are supported with kableExtra and flextable, but not simple data.frames. Here, one example with kableExtra:

x2 <- table1(~ age + wt | treat*sex, data=dat, overall=FALSE)
t1kable(x2)

Captions and footnotes

Captions and footnotes are supported with both kableExtra and flextable. An example with kableExtra:

x <- table1(~ age + sex + wt | treat, data=dat,
    caption="Test caption", footnote="Test footnote")
t1kable(x)

Alternatively, the kableExtra::footnote() function can be used to add footnotes to the resulting object (this function also does automatic numbering, which may be considered an advantage). Note that when a caption is used, the table is rendered as a float.

Closing remarks

As of version 1.4, it is now possible to use table1 within \LaTeX{} documents. There are some limitations on the formatting, however (it looks fine, but not quite the same as the HTML output and there is less flexibility to control it).

The actual \LaTeX{} code generation is handled by an external package (i.e., knitr, kableExtra or flextable). The \LaTeX{} generated by kableExtra and flextable is very different, and in my opinion kableExtra produces the better result. Both kableExtra and flextable have an extensive number of functions that can be applied to the converted object in order to alter the appearance of the table but these will not be described here; refer to each package's documentation for the complete details.



Try the table1 package in your browser

Any scripts or data that you put into this service are public.

table1 documentation built on Jan. 6, 2023, 5:07 p.m.