Demographic Table

Tingting Zhan

Introduction

This vignette of package DemographicTable (CRAN, Github) presents an idiot-proof interface to create a summary table of simple statistics, often known as a demographic table.

Package DemographicTable Imports packages

Prerequisite

Packages DemographicTable requires R version 4.5.0 (released 2025-04-11) or higher (macOS, Windows). An Integrated Development Environment (IDE), e.g., RStudio or Positron, is not required, but highly recommended. This vignette is created under R version 4.5.1 (2025-06-13) using packages knitr (Xie 2025, v1.50), quarto (Allaire and Dervieux 2025, v1.5.0 with Quarto v1.7.33) and rmarkdown (Allaire et al. 2024, v2.29).

Environment on author’s computer
Sys.info()[c('sysname', 'release', 'machine')]
#  sysname  release  machine 
# "Darwin" "24.6.0"  "arm64"
R.version
#                _                           
# platform       aarch64-apple-darwin20      
# arch           aarch64                     
# os             darwin20                    
# system         aarch64, darwin20           
# status                                     
# major          4                           
# minor          5.1                         
# year           2025                        
# month          06                          
# day            13                          
# svn rev        88306                       
# language       R                           
# version.string R version 4.5.1 (2025-06-13)
# nickname       Great Square Root

Experimental (and maybe unstable) features are released extremely frequently to Github. Stable releases to CRAN are typically updated every 2 to 3 months.

remotes::install_github('tingtingzhan/DemographicTable')
utils::install.packages('DemographicTable')

Getting Started

Examples in this vignette require that the search path has

library(DemographicTable)
library(flextable)

Users may remove the last pipe |> as_flextable() from all examples. This is required in the vignette to make quarto rendering work.

Demographic Table

Data example penguins from package datasets

Summary of all subjects

datasets::penguins |>
  DemographicTable(include = c('species', 'island', 'bill_len')) |> 
  as_flextable()

datasets::penguins

n=344

bill_len.
mean±sd
median; IQR
range

n*=342
43.9±5.5
44.5; 9.3
32.1~59.6

island: n (%).
Biscoe
Dream
Torgersen


168 (48.8%)
124 (36.0%)
52 (15.1%)

species: n (%).
Adelie
Chinstrap
Gentoo


152 (44.2%)
68 (19.8%)
124 (36.0%)

n=344

datasets::penguins

Summary by one group

Color of each individual group is determined by scales::pal_hue(), which is the default color pallete used in package ggplot2.

datasets::penguins |>
  DemographicTable(groups = 'sex', include = c('species', 'bill_dep')) |> 
  as_flextable()

datasets::penguins

n=344

sex
n=11 (3.2%) missing

female
n=165 (48.0%)

male
n=168 (48.8%)

Signif

bill_dep.
mean±sd
median; IQR
range

n*=342
17.2±2.0
17.3; 3.1
13.1~21.5


16.4±1.8
17.0; 3.3
13.1~20.7


17.9±1.9
18.4; 3.2
14.1~21.5

0.000★
Two-Sample t

species: n (%).
Adelie
Chinstrap
Gentoo


152 (44.2%)
68 (19.8%)
124 (36.0%)


73 (44.2%)
34 (20.6%)
58 (35.2%)


73 (43.5%)
34 (20.2%)
61 (36.3%)

0.979
Fisher's Exact

n=344

sex
n=11 (3.2%) missing

datasets::penguins

User may choose to hide the p-values with option compare = FALSE.

datasets::penguins |>
  DemographicTable(groups = 'sex', include = c('species', 'bill_dep'), compare = FALSE) |>
  as_flextable()

datasets::penguins

n=344

sex
n=11 (3.2%) missing

female
n=165 (48.0%)

male
n=168 (48.8%)

bill_dep.
mean±sd
median; IQR
range

n*=342
17.2±2.0
17.3; 3.1
13.1~21.5


16.4±1.8
17.0; 3.3
13.1~20.7


17.9±1.9
18.4; 3.2
14.1~21.5

species: n (%).
Adelie
Chinstrap
Gentoo


152 (44.2%)
68 (19.8%)
124 (36.0%)


73 (44.2%)
34 (20.6%)
58 (35.2%)


73 (43.5%)
34 (20.2%)
61 (36.3%)

n=344

sex
n=11 (3.2%) missing

datasets::penguins

Summary by multiple groups

datasets::penguins |>
  DemographicTable(groups = c('sex', 'island'), include = c('species', 'bill_dep'), compare = FALSE) |> 
  as_flextable()

datasets::penguins

n=344

sex
n=11 (3.2%) missing

island

female
n=165 (48.0%)

male
n=168 (48.8%)

Biscoe
n=168 (48.8%)

Dream
n=124 (36.0%)

Torgersen
n=52 (15.1%)

bill_dep.
mean±sd
median; IQR
range

n*=342
17.2±2.0
17.3; 3.1
13.1~21.5


16.4±1.8
17.0; 3.3
13.1~20.7


17.9±1.9
18.4; 3.2
14.1~21.5

n*=167
15.9±1.8
15.5; 2.5
13.1~21.1


18.3±1.1
.
15.5~21.2

n*=51
18.4±1.3
.
15.9~21.5

species: n (%).
Adelie
Chinstrap
Gentoo


152 (44.2%)
68 (19.8%)
124 (36.0%)


73 (44.2%)
34 (20.6%)
58 (35.2%)


73 (43.5%)
34 (20.2%)
61 (36.3%)


44 (26.2%)
-
124 (73.8%)


56 (45.2%)
68 (54.8%)
-


52 (100.0%)
-
-

n=344

sex
n=11 (3.2%) missing

island

datasets::penguins

Combine multiple DemographicTables

tb1 = datasets::penguins |>
  subset(subset = (sex == 'male')) |>
  DemographicTable(groups = 'island', include = c('species', 'bill_dep'), data.name = 'Male Penguins', compare = FALSE)
tb2 = datasets::penguins |>
  subset(subset = (sex == 'female')) |>
  DemographicTable(groups = 'island', include = c('species', 'bill_dep'), data.name = 'Female Penguins', compare = FALSE)
c(tb1, tb2) |> as_flextable()

Male Penguins

Female Penguins

n=168

island

n=165

island

Biscoe
n=83 (49.4%)

Dream
n=62 (36.9%)

Torgersen
n=23 (13.7%)

Biscoe
n=80 (48.5%)

Dream
n=61 (37.0%)

Torgersen
n=24 (14.5%)

bill_dep.
mean±sd
median; IQR
range


17.9±1.9
18.4; 3.2
14.1~21.5


16.6±1.7
16.0; 2.3
14.1~21.1


19.1±0.9
.
17.0~21.2


19.4±1.1
.
17.6~21.5


16.4±1.8
17.0; 3.3
13.1~20.7


15.2±1.7
14.5; 2.3
13.1~20.7


17.6±0.8
.
15.5~19.4


17.6±0.9
.
15.9~19.3

species: n (%).
Adelie
Chinstrap
Gentoo


73 (43.5%)
34 (20.2%)
61 (36.3%)


22 (26.5%)
-
61 (73.5%)


28 (45.2%)
34 (54.8%)
-


23 (100.0%)
-
-


73 (44.2%)
34 (20.6%)
58 (35.2%)


22 (27.5%)
-
58 (72.5%)


27 (44.3%)
34 (55.7%)
-


24 (100.0%)
-
-

n=168

island

n=165

island

Male Penguins

Female Penguins

Exception Handling

Missing value in groups

datasets::penguins |>
  DemographicTable(groups = c('sex'), include = c('body_mass', 'species')) |>
  as_flextable()

datasets::penguins

n=344

sex
n=11 (3.2%) missing

female
n=165 (48.0%)

male
n=168 (48.8%)

Signif

body_mass.
mean±sd
median; IQR
range

n*=342
4201.8±802.0
4050.0; 1200.0
2700.0~6300.0


3862.3±666.2
3650.0; 1200.0
2700.0~5200.0


4545.7±787.6
4300.0; 1412.5
3250.0~6300.0

0.000★
Two-Sample t

species: n (%).
Adelie
Chinstrap
Gentoo


152 (44.2%)
68 (19.8%)
124 (36.0%)


73 (44.2%)
34 (20.6%)
58 (35.2%)


73 (43.5%)
34 (20.2%)
61 (36.3%)

0.979
Fisher's Exact

n=344

sex
n=11 (3.2%) missing

datasets::penguins

Use of logical values

Using logical values is discouraged, as this practice is proved confusing to scientists without a strong data background.

mtc = datasets::mtcars |>
  within.data.frame(expr = {
    vs_straight = as.logical(vs)
    am_manual = as.logical(am)
  })

A warning message will be printed if logical variables are used in groups and/or include.

tryCatch(DemographicTable(mtc, groups = 'am_manual', include = c('drat', 'vs_straight')), warning = identity)
# <simpleWarning in DemographicTable(mtc, groups = "am_manual", include = c("drat",     "vs_straight")): 
# Some scientists do not understand logical value (e.g., arm_intervention being TRUE/FALSE)
# Consider using 2-level factor (e.g., arm being intervention/control)>

Instead of using logical variables

mtc |>
  DemographicTable(groups = 'am_manual', include = c('drat', 'vs_straight')) |>
  as_flextable()

mtc

n=32

am_manual

FALSE
n=19 (59.4%)

TRUE
n=13 (40.6%)

Signif

drat.
mean±sd
median; IQR
range


3.6±0.5
.
2.8~4.9


3.3±0.4
3.1; 0.6
2.8~3.9


4.0±0.4
.
3.5~4.9

0.000★
Wilcoxon-
Mann-Whitney

vs_straight: n (%)

14 (43.8%)

7 (36.8%)

7 (53.8%)

0.556
χ² (chi-square)

n=32

am_manual

mtc

We recommend using 2-level factors.

mtcars |>
  within.data.frame(expr = {
    vs = ifelse(vs, yes = 'Straight', no = 'V-shaped')
    am = ifelse(am, yes = 'manual', no = 'automatic')
  }) |> 
  DemographicTable(groups = 'am', include = c('drat', 'vs'), data.name = 'mtcars') |>
  as_flextable()

mtcars

n=32

am

automatic
n=19 (59.4%)

manual
n=13 (40.6%)

Signif

drat.
mean±sd
median; IQR
range


3.6±0.5
.
2.8~4.9


3.3±0.4
3.1; 0.6
2.8~3.9


4.0±0.4
.
3.5~4.9

0.000★
Wilcoxon-
Mann-Whitney

vs: n (%).
Straight
V-shaped


14 (43.8%)
18 (56.2%)


7 (36.8%)
12 (63.2%)


7 (53.8%)
6 (46.2%)

0.473
Fisher's Exact

n=32

am

mtcars

Allaire, JJ, and Christophe Dervieux. 2025. quarto: R Interface to ’Quarto’ Markdown Publishing System. https://doi.org/10.32614/CRAN.package.quarto.
Allaire, JJ, Yihui Xie, Christophe Dervieux, Jonathan McPherson, Javier Luraschi, Kevin Ushey, Aron Atkins, et al. 2024. rmarkdown: Dynamic Documents for r. https://github.com/rstudio/rmarkdown.
Csárdi, Gábor. 2025. cli: Helpers for Developing Command Line Interfaces. https://doi.org/10.32614/CRAN.package.cli.
Gohel, David, Stefan Moog, and Mark Heckmann. 2025. officer: Manipulation of Microsoft Word and PowerPoint Documents. https://doi.org/10.32614/CRAN.package.officer.
Gohel, David, and Panagiotis Skintzos. 2025. flextable: Functions for Tabular Reporting. https://doi.org/10.32614/CRAN.package.flextable.
Wickham, Hadley, Thomas Lin Pedersen, and Dana Seidel. 2025. scales: Scale Functions for Visualization. https://doi.org/10.32614/CRAN.package.scales.
Xie, Yihui. 2025. knitr: A General-Purpose Package for Dynamic Report Generation in R. https://yihui.org/knitr/.