A nice image.
The {gtsummary}
package provides an elegant and flexible way to create publication-ready and reproducible analytical tables. see https://cran.r-project.org/web/packages/gtsummary/index.html.
library(knitr)
library(gtsummary)
library(tidyverse)
Open data trial
head(trial)
## # A tibble: 6 x 8
## trt age marker stage grade response death ttdeath
## <chr> <dbl> <dbl> <fct> <fct> <int> <int> <dbl>
## 1 Drug A 23 0.16 T1 II 0 0 24
## 2 Drug B 9 1.11 T2 I 1 0 24
## 3 Drug A 31 0.277 T1 II 0 0 24
## 4 Drug A NA 2.07 T3 III 1 1 17.6
## 5 Drug A 51 2.77 T4 III 1 1 16.4
## 6 Drug B 39 0.613 T4 I 0 1 15.6
# make dataset with a few variables to summarize
trial2 <- trial %>%
select(trt, age, grade, response)
head(trial2)
## # A tibble: 6 x 4
## trt age grade response
## <chr> <dbl> <fct> <int>
## 1 Drug A 23 II 0
## 2 Drug B 9 I 1
## 3 Drug A 31 II 0
## 4 Drug A NA III 1
## 5 Drug A 51 III 1
## 6 Drug B 39 I 0
Use tbl_summary(data)
# summarize the data with 'gtsummary' package
table1 <- tbl_summary(trial2,
missing = "no" # don't list missing data separately
)
table1
Characteristic | N = 2001 |
---|---|
Chemotherapy Treatment | |
Drug A | 98 (49%) |
Drug B | 102 (51%) |
Age, yrs | 47 (38, 57) |
Grade | |
I | 68 (34%) |
II | 68 (34%) |
III | 64 (32%) |
Tumor Response | 61 (32%) |
1
Statistics presented: n (%); median (IQR)
|
Use tbl_summary(data,by=var)
table2 <- tbl_summary(
trial2,
by = trt, # split table by group
missing = "no" # don't list missing data separately
) %>%
add_n() %>% # add column with total number of non-missing observations
add_p() %>% # test if there's difference between groups
bold_labels()
table2
Characteristic | N | Drug A, N = 981 | Drug B, N = 1021 | p-value2 |
---|---|---|---|---|
Age, yrs | 189 | 46 (37, 59) | 48 (39, 56) | 0.7 |
Grade | 200 | 0.9 | ||
I | 35 (36%) | 33 (32%) | ||
II | 32 (33%) | 36 (35%) | ||
III | 31 (32%) | 33 (32%) | ||
Tumor Response | 193 | 28 (29%) | 33 (34%) | 0.6 |
1
Statistics presented: median (IQR); n (%)
2
Statistical tests performed: Wilcoxon rank-sum test; chi-square test of independence
|
Use tbl_summary(data,by=var)
table3 <- tbl_summary(
trial2,
by = trt, # split table by group
statistic = list( # Add statistic
all_continuous() ~ "{mean} ({sd})",
all_categorical() ~ "{n} / {N} ({p}%)"),
missing = "no", # don't list missing data separately
label = age ~ "Patient Age" # Change level
) %>%
add_n() %>% # add column with total number of non-missing observations
add_p(test = list(all_continuous() ~ "t.test",
response ~ "fisher.test"))%>%
bold_labels()
table3
Characteristic | N | Drug A, N = 981 | Drug B, N = 1021 | p-value2 |
---|---|---|---|---|
Patient Age | 189 | 47 (15) | 47 (14) | 0.8 |
Grade | 200 | 0.9 | ||
I | 35 / 98 (36%) | 33 / 102 (32%) | ||
II | 32 / 98 (33%) | 36 / 102 (35%) | ||
III | 31 / 98 (32%) | 33 / 102 (32%) | ||
Tumor Response | 193 | 28 / 95 (29%) | 33 / 98 (34%) | 0.5 |
1
Statistics presented: mean (SD); n / N (%)
2
Statistical tests performed: t-test; chi-square test of independence; Fisher's exact test
|
Use tbl_regression(model)
mod1 <- glm(response ~ trt + age + grade, trial, family = binomial)
t1 <- tbl_regression(mod1, exponentiate = TRUE)
t1
Characteristic | OR1 | 95% CI1 | p-value |
---|---|---|---|
Chemotherapy Treatment | |||
Drug A | — | — | |
Drug B | 1.13 | 0.60, 2.13 | 0.7 |
Age, yrs | 1.02 | 1.00, 1.04 | 0.10 |
Grade | |||
I | — | — | |
II | 0.85 | 0.39, 1.85 | 0.7 |
III | 1.01 | 0.47, 2.15 | >0.9 |
1
OR = Odds Ratio, CI = Confidence Interval
|
Use tbl_merge()
library(survival)
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_ex1 <-
tbl_merge(
tbls = list(t1, t2),
tab_spanner = c("**Tumor Response**", "**Time to Death**")
)
tbl_merge_ex1
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, yrs | 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
|