Tables

Display data in attractive, compact formats

There are a number of options available for displaying tables within Distill articles, including:

Knitr kable

The knitr::kable() function will render an R data frame as an HTML table. For example:

```{r, layout="l-body-outset"}
library(knitr)
kable(head(mtcars))
```
library(knitr)
kable(head(mtcars))
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

Often times tables will require more width for their display than the standard Distill article text width. Here we use layout="l-body-outset" to cause the table to outset slightly from the main text column. All of the available figure layouts can also be used with tables.

Paged tables

If a data frame has a large number of rows it might not be practical to display it fully inline. In these situations you can use the rmarkdown::paged_table() function to create a table that allows pagination of rows and columns. For example:

```{r, layout="l-body-outset"}
library(rmarkdown)
paged_table(mtcars)
```

There are a number of options available that control the display of paged tables. By default, 10 rows at a time are displayed but you can use the rows.print option to increase this. For example:

```{r, layout="l-body-outset"}
library(rmarkdown)
paged_table(mtcars, options = list(rows.print = 15))
```
library(rmarkdown)
paged_table(mtcars, options = list(rows.print = 15, cols.print = 5))

Here is a summary of the available paged table options:

Option Description
rows.print Maximum rows to print per page.
max.print Maximum rows in the table (defaults to 1000).
cols.print Maximum columns in the table (defaults to 10).
rownames.print Print row names as part of the table.

gtsummary tables

The gtsummary package provides an elegant and flexible way to create publication-ready analytical and summary tables. The package summarizes data sets, regression models, and more, using sensible defaults with highly customizable capabilities. For example:

```{r}
library(gtsummary)
library(survival)

# build glm table
mod1 <- glm(response ~ trt + age + grade, trial, family = binomial)
t1 <- tbl_regression(mod1, exponentiate = TRUE)

# build survival model table
t2 <-
  coxph(Surv(ttdeath, death) ~ trt + grade + age, trial) %>%
  tbl_regression(exponentiate = TRUE)

# merge tables 
tbl_merge(
  tbls = list(t1, t2),
  tab_spanner = c("**Tumor Response**", "**Time to Death**")
)
```
library(gtsummary)
library(survival)

# build glm table
mod1 <- glm(response ~ trt + age + grade, trial, family = binomial)
t1 <- tbl_regression(mod1, exponentiate = TRUE)

# build survival model table
t2 <-
  coxph(Surv(ttdeath, death) ~ trt + grade + age, trial) %>%
  tbl_regression(exponentiate = TRUE)

# merge tables 
tbl_merge(
  tbls = list(t1, t2),
  tab_spanner = c("**Tumor Response**", "**Time to Death**")
)
Characteristic Tumor Response Time to Death
OR1 95% CI1 p-value HR1 95% CI1 p-value
Chemotherapy Treatment
Drug A
Drug B 1.13 0.60, 2.13 0.7 1.30 0.88, 1.92 0.2
Age 1.02 1.00, 1.04 0.10 1.01 0.99, 1.02 0.3
Grade
I
II 0.85 0.39, 1.85 0.7 1.21 0.73, 1.99 0.5
III 1.01 0.47, 2.15 >0.9 1.79 1.12, 2.86 0.014

1 OR = Odds Ratio, CI = Confidence Interval, HR = Hazard Ratio

gt tables

The gtsummary package is built in top of the gt package, which provides a flexible foundation for creating just about any sort of table you can imagine. Here is a brief example of how to use gt to create a table from the included sp500 dataset:

```{r}
library(gt)
library(tidyverse)
library(glue)

# Define the start and end dates for the data range
start_date <- "2010-06-07"
end_date <- "2010-06-14"

# Create a gt table based on preprocessed
# `sp500` table data
sp500 %>%
  dplyr::filter(date >= start_date & date <= end_date) %>%
  dplyr::select(-adj_close) %>%
  gt() %>%
  tab_header(
    title = "S&P 500",
    subtitle = glue::glue("{start_date} to {end_date}")
  ) %>%
  fmt_date(
    columns = vars(date),
    date_style = 3
  ) %>%
  fmt_currency(
    columns = vars(open, high, low, close),
    currency = "USD"
  ) %>%
  fmt_number(
    columns = vars(volume),
    suffixing = TRUE
  )
```
library(gt)
library(tidyverse)
library(glue)

# Define the start and end dates for the data range
start_date <- "2010-06-07"
end_date <- "2010-06-14"

# Create a gt table based on preprocessed
# `sp500` table data
sp500 %>%
  dplyr::filter(date >= start_date & date <= end_date) %>%
  dplyr::select(-adj_close) %>%
  gt() %>%
  tab_header(
    title = "S&P 500",
    subtitle = glue::glue("{start_date} to {end_date}")
  ) %>%
  fmt_date(
    columns = vars(date),
    date_style = 3
  ) %>%
  fmt_currency(
    columns = vars(open, high, low, close),
    currency = "USD"
  ) %>%
  fmt_number(
    columns = vars(volume),
    suffixing = TRUE
  )
S&P 500
2010-06-07 to 2010-06-14
date open high low close volume
Mon, Jun 14, 2010 $1,095.00 $1,105.91 $1,089.03 $1,089.63 4.43B
Fri, Jun 11, 2010 $1,082.65 $1,092.25 $1,077.12 $1,091.60 4.06B
Thu, Jun 10, 2010 $1,058.77 $1,087.85 $1,058.77 $1,086.84 5.14B
Wed, Jun 9, 2010 $1,062.75 $1,077.74 $1,052.25 $1,055.69 5.98B
Tue, Jun 8, 2010 $1,050.81 $1,063.15 $1,042.17 $1,062.00 6.19B
Mon, Jun 7, 2010 $1,065.84 $1,071.36 $1,049.86 $1,050.47 5.47B

Markdown tables

You can also define tables using markdown. For example, the table from the previous section that describes paged table options was defined with the following markdown:

| Option           | Description                                    |
|------------------|------------------------------------------------|
| `rows.print`     | Maximum rows to print per page.                |
| `max.print`      | Maximum rows in the table (defaults to 1000).  |
| `cols.print`     | Maximum columns in the table (defaults to 10). |
| `rownames.print` | Print row names as part of the table.          |

You can use Distill figure layout classes with markdown tables by enclosing them in markdown div (:::) named with the appropriate class, for example:

::: l-body-outset
| Option           | Description                                    |
|------------------|------------------------------------------------|
| `rows.print`     | Maximum rows to print per page.                |
| `max.print`      | Maximum rows in the table (defaults to 1000).  |
| `cols.print`     | Maximum columns in the table (defaults to 10). |
| `rownames.print` | Print row names as part of the table.          |
:::

Corrections

If you see mistakes or want to suggest changes, please create an issue on the source repository.

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. Source code is available at https://github.com/rstudio/distill, unless otherwise noted. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".