ltsummary tables are rendered by the lt package, which builds the HTML table in the browser from a small JSON specification. That makes HTML output the native format, and it is the format this website uses. Other formats are reached through lt’s static rendering or by exporting the table to a file. This article says what works where, and how.
Output types
| Format | How | Result |
|---|---|---|
| HTML (Quarto, R Markdown, litedown) | print the table | full output |
| GitHub Flavored Markdown | print the table with the static option set | full output |
| Word and PDF (Quarto) | print the table with the static option set | native table; indentation and bold cells are lost |
| Word and PDF (R Markdown) | export to PNG and include the image | image of the full table |
| PNG, PDF and HTML files | lt::lt_export() |
full output |
HTML
Printing a table in a chunk is enough. The package registers methods
for knitr::knit_print() and for litedown’s
xfun::record_print(), so the table renders in Quarto, R
Markdown and litedown documents without any extra code.
The JavaScript and CSS that lt needs are emitted once per document, with the first table.
Word and PDF with Quarto
lt can bake a static <table> instead of the
JavaScript specification. Set the lt.lt_static option at
the top of the document and print tables as usual; Quarto then converts
the HTML table into a native Word or LaTeX table.
```{r}
#| include: false
options(lt.lt_static = list(fragment = TRUE, css = FALSE))
library(ltsummary)
```
```{r}
tbl_summary(trial, by = trt, include = c(age, grade)) |> add_p() |> bold_labels()
```Baking the table needs Node.js or a Chromium-based browser on the
machine that renders the document; lt finds either on its own. The
conversion keeps the headers, the values and the footnotes, and drops
the inline styles, so the indentation of the levels and bold or italic
cells do not survive. This is the same limitation that gtsummary
documents for its kable output.
The same option makes the table render in GitHub Flavored Markdown, for example in a README built from an R Markdown file, because GitHub displays raw HTML tables.
Word and PDF with R Markdown
Pandoc drops raw HTML when it writes Word or LaTeX, so in R Markdown the static option is not enough. Export the table to an image and include it:
```{r, echo = FALSE}
tbl <- tbl_summary(trial, by = trt, include = c(age, grade)) |> add_p()
lt::lt_export(as_lt(tbl), "table1.png")
knitr::include_graphics("table1.png")
```The image is cropped to the table and keeps every formatting feature.
lt_export() renders through a headless Chromium browser;
cropping PNG output also needs the magick package.
Alternatively, switch to Quarto for the document: the Quarto route above gives a real table that Word users can edit.
Images and files
lt::lt_export() writes a table to disk. The file
extension chooses the format: .html for a standalone web
page, .pdf for a vector PDF, and anything else for a
PNG.
tbl <- tbl_summary(trial, by = trt, include = c(age, grade)) |> add_p()
lt::lt_export(as_lt(tbl), "table1.html")
lt::lt_export(as_lt(tbl), "table1.pdf")
lt::lt_export(as_lt(tbl), "table1.png", width = 500)The README of the package is built this way: the table is exported to PNG and the image is included, which is why it shows on GitHub.
Plain text
as.data.frame() returns the formatted cells as a data
frame, with the header labels as column names. Print it, or pass it to
knitr::kable(), when a plain table is all that is needed.
The data.frame print engine does the same at the
console.
tbl <- tbl_summary(trial, by = trt, include = c(age, grade)) |> add_p()
as.data.frame(tbl)
#> **Characteristic** **Drug A** \nN = 95 **Drug B** \nN = 105 **p-value**
#> 1 Age 59 (51, 66) 62 (54, 71) 0.043
#> 2 Unknown 4 7 <NA>
#> 3 Grade <NA> <NA> 0.3
#> 4 I 25 (26%) 37 (35%) <NA>
#> 5 II 40 (42%) 43 (41%) <NA>
#> 6 III 30 (32%) 25 (24%) <NA>The header labels carry markdown (**Drug A**) and line
breaks, which kable() does not interpret, and empty cells
are NA. Tidy both before passing the data frame on:
df <- as.data.frame(tbl)
names(df) <- gsub(" \n", ", ", gsub("**", "", names(df), fixed = TRUE))
df[is.na(df)] <- ""
knitr::kable(df)| Characteristic | Drug A, N = 95 | Drug B, N = 105 | p-value |
|---|---|---|---|
| Age | 59 (51, 66) | 62 (54, 71) | 0.043 |
| Unknown | 4 | 7 | |
| Grade | 0.3 | ||
| I | 25 (26%) | 37 (35%) | |
| II | 40 (42%) | 43 (41%) | |
| III | 30 (32%) | 25 (24%) |
Tips
When printing tables in a loop, use print() in a chunk
with results = "asis":
```{r loop_print, results = "asis"}
for (v in c("age", "grade")) {
tbl <- tbl_summary(trial, by = trt, include = all_of(v))
print(tbl)
}
```If print(tbl) does not render, try
knitr::knit_print(tbl) or
cat(knitr::knit_print(tbl)).
inline_text() quotes the table in the text; the inline_text() tutorial shows how.