Demographic Table

Tingting Zhan

2026-09-25

1 Introduction

utils::install.packages('DemographicTable')

1.1 Getting Started

Examples in this vignette requires

library(DemographicTable)

Users may remove the last pipe |> print() from all examples if they are using R interactively.

2 Demographic Table

2.1 Summary of all subjects

datasets::penguins |>
  subset.data.frame(select = c('species', 'island', 'bill_len')) |>
  DemographicTable(data.name = 'datasets::penguins') |>
  print()

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

species: n (%).
 Adelie
 Chinstrap
 Gentoo


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

island: n (%).
 Biscoe
 Dream
 Torgersen


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

n=344

datasets::penguins

2.2 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.

Listing 1: penguins by sex
datasets::penguins |>
  subset.data.frame(select = c('sex', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ sex, data.name = 'datasets::penguins') |> 
  print()

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

sex: n (%).
 female
 male

n*=333
165 (49.5%)
168 (50.5%)


165 (100.0%)
-


-
168 (100.0%)

★ 0.000
Fisher's Exact

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 |>
  subset.data.frame(select = c('sex', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ sex, data.name = 'datasets::penguins', compare = FALSE) |>
  print()

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

sex: n (%).
 female
 male

n*=333
165 (49.5%)
168 (50.5%)


165 (100.0%)
-


-
168 (100.0%)

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

2.3 Summary by multiple groups

datasets::penguins |>
  subset.data.frame(select = c('sex', 'island', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ sex + island, data.name = 'datasets::penguins', compare = FALSE) |> 
  print()

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

sex: n (%).
 female
 male

n*=333
165 (49.5%)
168 (50.5%)


165 (100.0%)
-


-
168 (100.0%)

n*=163
80 (49.1%)
83 (50.9%)

n*=123
61 (49.6%)
62 (50.4%)

n*=47
24 (51.1%)
23 (48.9%)

island: n (%).
 Biscoe
 Dream
 Torgersen


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


80 (48.5%)
61 (37.0%)
24 (14.5%)


83 (49.4%)
62 (36.9%)
23 (13.7%)


168 (100.0%)
-
-


-
124 (100.0%)
-


-
-
52 (100.0%)

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

3 Combine Multiple DemographicTables

male = datasets::penguins |>
  subset(subset = (sex == 'male'), select = c('island', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ island, data.name = 'Male Penguins', compare = FALSE)
female = datasets::penguins |>
  subset(subset = (sex == 'female'), select = c('island', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ island, data.name = 'Female Penguins', compare = FALSE)
c(male, female) |> 
  print()

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

island: n (%).
 Biscoe
 Dream
 Torgersen


83 (49.4%)
62 (36.9%)
23 (13.7%)


83 (100.0%)
-
-


-
62 (100.0%)
-


-
-
23 (100.0%)


80 (48.5%)
61 (37.0%)
24 (14.5%)


80 (100.0%)
-
-


-
61 (100.0%)
-


-
-
24 (100.0%)

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

4 Advance Usage

Remove the “overall” column.

tb = datasets::penguins |>
  subset.data.frame(select = c('sex', 'island', 'species', 'bill_dep')) |>
  DemographicTable(by = ~ sex + island, data.name = 'datasets::penguins', compare = FALSE)
tb[-1L] |> 
  print()

datasets::penguins

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


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

sex: n (%).
 female
 male


165 (100.0%)
-


-
168 (100.0%)

n*=163
80 (49.1%)
83 (50.9%)

n*=123
61 (49.6%)
62 (50.4%)

n*=47
24 (51.1%)
23 (48.9%)

island: n (%).
 Biscoe
 Dream
 Torgersen


80 (48.5%)
61 (37.0%)
24 (14.5%)


83 (49.4%)
62 (36.9%)
23 (13.7%)


168 (100.0%)
-
-


-
124 (100.0%)
-


-
-
52 (100.0%)

species: n (%).
 Adelie
 Chinstrap
 Gentoo


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%)
-
-

sex
n=11 (3.2%) missing

island

datasets::penguins

c(male, female)[2:4] |> 
  print()

Male Penguins

Female Penguins

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


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

island: n (%).
 Biscoe
 Dream
 Torgersen


83 (100.0%)
-
-


-
62 (100.0%)
-


-
-
23 (100.0%)


80 (48.5%)
61 (37.0%)
24 (14.5%)


80 (100.0%)
-
-


-
61 (100.0%)
-


-
-
24 (100.0%)

species: n (%).
 Adelie
 Chinstrap
 Gentoo


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%)
-
-

island

n=165

island

Male Penguins

Female Penguins

c(male, female)[c(2L, 4L)] |> 
  print()

Male Penguins

Female Penguins

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


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


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

island: n (%).
 Biscoe
 Dream
 Torgersen


83 (100.0%)
-
-


-
62 (100.0%)
-


-
-
23 (100.0%)


80 (100.0%)
-
-


-
61 (100.0%)
-


-
-
24 (100.0%)

species: n (%).
 Adelie
 Chinstrap
 Gentoo


22 (26.5%)
-
61 (73.5%)


28 (45.2%)
34 (54.8%)
-


23 (100.0%)
-
-


22 (27.5%)
-
58 (72.5%)


27 (44.3%)
34 (55.7%)
-


24 (100.0%)
-
-

island

Male Penguins

Female Penguins

5 Exception Handling

5.1 Missing value in one or more groups

See Listing 1.

5.2 Use of logical values

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

Listing 2: Using logical values is discouraged
datasets::mtcars |>
  within.data.frame(expr = {
    vs_straight = as.logical(vs)
    am_manual = as.logical(am)
  }) |>
  subset.data.frame(select = c('am_manual', 'drat', 'vs_straight')) |>
  DemographicTable(by = ~ am_manual, data.name = 'mtcars') |>
  print()

mtcars

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

am_manual: n (%)

13 (40.6%)

-

13 (100.0%)

vs_straight: n (%)

14 (43.8%)

7 (36.8%)

7 (53.8%)

0.556
χ² (chi-square)

n=32

am_manual

mtcars

Instead of using logical variables, we recommend using 2-level factors (Listing 3).

Listing 3: We recommend using 2-level factors
datasets::mtcars |>
  within.data.frame(expr = {
    vs = ifelse(vs, yes = 'Straight', no = 'V-shaped')
    am = ifelse(am, yes = 'manual', no = 'automatic')
  }) |> 
  subset.data.frame(select = c('am', 'drat', 'vs')) |>
  DemographicTable(by = ~ am, data.name = 'mtcars') |>
  print()

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

am: n (%).
 automatic
 manual


19 (59.4%)
13 (40.6%)


19 (100.0%)
-


-
13 (100.0%)

★ 0.000
Fisher's Exact

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