library(sjtable2df)
library(mlbench)
# load data
data("BreastCancer")
dataset <- BreastCancer |>
data.table::as.data.table() |>
na.omit()The sjPlot R package is a great package for visualizing results.
However, the tables created using the functions sjPlot::tab_model or sjPlot::tab_xtab return HTML tables and are not straightforward to use in R, especially when trying to integrate them into pdf- or word-documents using Rmarkdown.
Various approaches/ tutorials exist to convert sjPlot HTML tables to R data.frame objects:
None of these approaches converts sjPlot HTML tables to R data.frame objects or integrates well with knitr::kable or the kableExtra R package.
The sjtable2df R package’s goal is to overcome this and to provide an easy interface for converting sjPlot’s HTML tables to data.frame, data.table, or kable objects for further usage in R or Rmarkdown.
Currently, sjtable2df provides two functions to convert tables created from sjPlot’s functions tab_model and tab_xtab: sjtable2df::mtab2df and sjtable2df::xtab2df.
library(sjtable2df)
library(mlbench)
# load data
data("BreastCancer")
dataset <- BreastCancer |>
data.table::as.data.table() |>
na.omit()xtab <- sjPlot::tab_xtab(
var.row = dataset$Class,
var.col = dataset$Mitoses,
show.summary = TRUE,
use.viewer = FALSE
)xtab| Class | Mitoses | Total | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ||
| benign | 431 | 8 | 2 | 0 | 1 | 0 | 1 | 1 | 0 | 444 |
| malignant | 132 | 27 | 31 | 12 | 5 | 3 | 8 | 7 | 14 | 239 |
| Total | 563 | 35 | 33 | 12 | 6 | 3 | 9 | 8 | 14 | 683 |
| χ2=191.968 · df=8 · Cramer's V=0.530 · Fisher's p=0.000 | ||||||||||
data.framextab_df <- sjtable2df::xtab2df(xtab = xtab, output = "data.frame")
class(xtab_df)[1] "data.frame"
xtab_df Class Mitoses 1 Mitoses 2 Mitoses 3 Mitoses 4 Mitoses 5 Mitoses 6
1 benign 431 8 2 0 1 0
2 malignant 132 27 31 12 5 3
3 Total 563 35 33 12 6 3
4
Mitoses 7 Mitoses 8 Mitoses 10
1 1 1 0
2 8 7 14
3 9 8 14
4
Total
1 444
2 239
3 683
4 χ2=191.968 · df=8 · Cramer's V=0.530 · Fisher's p=0.000
kablextab_kbl <- sjtable2df::xtab2df(
xtab = xtab,
output = "kable",
caption = "Class vs. Mitoses"
)
class(xtab_kbl)[1] "kableExtra" "knitr_kable"
This function also extracts further statistics from cells and writes them to parentheses:
xtab <- sjPlot::tab_xtab(
var.row = dataset$Class,
var.col = dataset$Mitoses,
show.summary = TRUE,
show.col.prc = TRUE,
use.viewer = FALSE
)xtab| Class | Mitoses | Total | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 10 | ||
| benign | 431 76.6 % |
8 22.9 % |
2 6.1 % |
0 0 % |
1 16.7 % |
0 0 % |
1 11.1 % |
1 12.5 % |
0 0 % |
444 65 % |
| malignant | 132 23.4 % |
27 77.1 % |
31 93.9 % |
12 100 % |
5 83.3 % |
3 100 % |
8 88.9 % |
7 87.5 % |
14 100 % |
239 35 % |
| Total | 563 100 % |
35 100 % |
33 100 % |
12 100 % |
6 100 % |
3 100 % |
9 100 % |
8 100 % |
14 100 % |
683 100 % |
| χ2=191.968 · df=8 · Cramer's V=0.530 · Fisher's p=0.000 | ||||||||||
data.framextab_df <- sjtable2df::xtab2df(xtab = xtab, output = "data.frame")
xtab_df Class Mitoses 1 Mitoses 2 Mitoses 3 Mitoses 4 Mitoses 5
1 benign 431 (76.6 %) 8 (22.9 %) 2 (6.1 %) 0 (0 %) 1 (16.7 %)
2 malignant 132 (23.4 %) 27 (77.1 %) 31 (93.9 %) 12 (100 %) 5 (83.3 %)
3 Total 563 (100 %) 35 (100 %) 33 (100 %) 12 (100 %) 6 (100 %)
4
Mitoses 6 Mitoses 7 Mitoses 8 Mitoses 10
1 0 (0 %) 1 (11.1 %) 1 (12.5 %) 0 (0 %)
2 3 (100 %) 8 (88.9 %) 7 (87.5 %) 14 (100 %)
3 3 (100 %) 9 (100 %) 8 (100 %) 14 (100 %)
4
Total
1 444 (65 %)
2 239 (35 %)
3 683 (100 %)
4 χ2=191.968 · df=8 · Cramer's V=0.530 · Fisher's p=0.000
num_vars <- c("Cell.size", "Cell.shape")
dataset[, (num_vars) := lapply(.SD, as.integer), .SDcols = num_vars]
m0 <- lm(
Cell.size ~ 1,
data = dataset
)
m1 <- lm(
Cell.size ~ Cell.shape,
data = dataset
)
m2 <- lm(
Cell.size ~ Cell.shape + Class,
data = dataset
)m_table <- sjPlot::tab_model(
m0,
m1,
m2,
show.aic = TRUE
)m_table| Cell.size | Cell.size | Cell.size | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Estimates | CI | p | Estimates | CI | p | Estimates | CI | p |
| (Intercept) | 3.15 | 2.92 – 3.38 | <0.001 | 0.16 | 0.02 – 0.30 | 0.029 | 0.27 | 0.13 – 0.40 | <0.001 |
| Cell shape | 0.93 | 0.90 – 0.96 | <0.001 | 0.74 | 0.68 – 0.79 | <0.001 | |||
| Class [malignant] | 1.49 | 1.15 – 1.83 | <0.001 | ||||||
| Observations | 683 | 683 | 683 | ||||||
| R2 / R2 adjusted | 0.000 / 0.000 | 0.823 / 0.823 | 0.840 / 0.840 | ||||||
| AIC | 3471.319 | 2290.389 | 2221.652 | ||||||
data.framemtab_df <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "data.frame"
)
class(mtab_df)[1] "data.frame"
mtab_df Predictors Estimates CI p Estimates CI
1 (Intercept) 3.15 2.92 – 3.38 <0.001 0.16 0.02 – 0.30
2 Cell shape 0.93 0.90 – 0.96
3 Class [malignant]
4 Observations 683 683
5 R2 / R2 adjusted 0.000 / 0.000 0.823 / 0.823
6 AIC 3471.319 2290.389
p Estimates CI p
1 0.029 0.27 0.13 – 0.40 <0.001
2 <0.001 0.74 0.68 – 0.79 <0.001
3 1.49 1.15 – 1.83 <0.001
4 683
5 0.840 / 0.840
6 2221.652
kablemtab_kbl <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "kable"
)
class(mtab_kbl)[1] "kableExtra" "knitr_kable"
mtab_kbl| Predictors | Estimates | CI | p | Estimates | CI | p | Estimates | CI | p |
|---|---|---|---|---|---|---|---|---|---|
| (Intercept) | 3.15 | 2.92 – 3.38 | <0.001 | 0.16 | 0.02 – 0.30 | 0.029 | 0.27 | 0.13 – 0.40 | <0.001 |
| Cell shape | 0.93 | 0.90 – 0.96 | <0.001 | 0.74 | 0.68 – 0.79 | <0.001 | |||
| Class [malignant] | 1.49 | 1.15 – 1.83 | <0.001 | ||||||
| Observations | 683 | 683 | 683 | ||||||
| $R^2$ / $R^2$ adjusted | 0.000 / 0.000 | 0.823 / 0.823 | 0.840 / 0.840 | ||||||
| AIC | 3471.319 | 2290.389 | 2221.652 |
m0 <- stats::glm(
Class ~ 1,
data = dataset,
family = binomial(link = "logit")
)
m1 <- stats::glm(
Class ~ Cell.shape,
data = dataset,
family = binomial(link = "logit")
)
m2 <- stats::glm(
Class ~ Cell.shape + Cell.size,
data = dataset,
family = binomial(link = "logit")
)m_table <- sjPlot::tab_model(
m0,
m1,
m2,
show.aic = TRUE
)m_table| Class | Class | Class | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
| (Intercept) | 0.54 | 0.46 – 0.63 | <0.001 | 0.01 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| Cell shape | 4.36 | 3.50 – 5.62 | <0.001 | 2.31 | 1.71 – 3.19 | <0.001 | |||
| Cell size | 2.35 | 1.73 – 3.32 | <0.001 | ||||||
| Observations | 683 | 683 | 683 | ||||||
| R2 Tjur | 0.000 | 0.756 | 0.812 | ||||||
| AIC | 886.350 | 271.586 | 227.110 | ||||||
data.framemtab_df <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "data.frame"
)
class(mtab_df)[1] "data.frame"
mtab_df Predictors Odds Ratios CI p Odds Ratios CI p
1 (Intercept) 0.54 0.46 – 0.63 <0.001 0.01 0.00 – 0.01 <0.001
2 Cell shape 4.36 3.50 – 5.62 <0.001
3 Cell size
4 Observations 683 683
5 R2 Tjur 0.000 0.756
6 AIC 886.350 271.586
Odds Ratios CI p
1 0.00 0.00 – 0.01 <0.001
2 2.31 1.71 – 3.19 <0.001
3 2.35 1.73 – 3.32 <0.001
4 683
5 0.812
6 227.110
kablemtab_kbl <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "kable"
)
class(mtab_kbl)[1] "kableExtra" "knitr_kable"
mtab_kbl| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
|---|---|---|---|---|---|---|---|---|---|
| (Intercept) | 0.54 | 0.46 – 0.63 | <0.001 | 0.01 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| Cell shape | 4.36 | 3.50 – 5.62 | <0.001 | 2.31 | 1.71 – 3.19 | <0.001 | |||
| Cell size | 2.35 | 1.73 – 3.32 | <0.001 | ||||||
| Observations | 683 | 683 | 683 | ||||||
| $R^2$ Tjur | 0.000 | 0.756 | 0.812 | ||||||
| AIC | 886.350 | 271.586 | 227.110 |
set.seed(1)
dataset$city <- sample(
x = paste0("city_", 1:7),
size = nrow(dataset),
replace = TRUE
)
m0 <- lme4::glmer(
Class ~ 1 + (1 | city),
data = dataset,
family = binomial(link = "logit")
)boundary (singular) fit: see help('isSingular')
m1 <- lme4::glmer(
Class ~ Cell.size + (1 | city),
data = dataset,
family = binomial(link = "logit")
)
m2 <- lme4::glmer(
Class ~ Cell.size + log(Cell.shape) + (1 | city),
data = dataset,
family = binomial(link = "logit")
)boundary (singular) fit: see help('isSingular')
m_table <- sjPlot::tab_model(
m0,
m1,
m2,
show.aic = TRUE
)boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
boundary (singular) fit: see help('isSingular')
m_table| Class | Class | Class | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
| (Intercept) | 0.54 | 0.46 – 0.63 | <0.001 | 0.01 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| Cell size | 5.11 | 3.87 – 6.73 | <0.001 | 2.10 | 1.55 – 2.83 | <0.001 | |||
| Cell shape [log] | 15.55 | 6.55 – 36.89 | <0.001 | ||||||
| Random Effects | |||||||||
| σ2 | 3.29 | 3.29 | 3.29 | ||||||
| τ00 | 0.00 city | 0.12 city | 0.00 city | ||||||
| ICC | 0.03 | ||||||||
| N | 7 city | 7 city | 7 city | ||||||
| Observations | 683 | 683 | 683 | ||||||
| Marginal R2 / Conditional R2 | 0.000 / NA | 0.880 / 0.884 | 0.861 / NA | ||||||
| AIC | 888.350 | 259.874 | 214.461 | ||||||
data.framemtab_df <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "data.frame"
)
class(mtab_df)[1] "data.frame"
mtab_df Predictors Odds Ratios CI p Odds Ratios
1 (Intercept) 0.54 0.46 – 0.63 <0.001 0.01
2 Cell size 5.11
3 Cell shape [log]
4 Random Effects
5 σ2 3.29 3.29
6 τ00 0.00 city 0.12 city
7 ICC 0.03
8 N 7 city 7 city
9 Observations 683 683
10 Marginal R2 / Conditional R2 0.000 / NA 0.880 / 0.884
11 AIC 888.350 259.874
CI p Odds Ratios CI p
1 0.00 – 0.01 <0.001 0.00 0.00 – 0.01 <0.001
2 3.87 – 6.73 <0.001 2.10 1.55 – 2.83 <0.001
3 15.55 6.55 – 36.89 <0.001
4
5 3.29
6 0.00 city
7
8 7 city
9 683
10 0.861 / NA
11 214.461
kablemtab_kbl <- sjtable2df::mtab2df(
mtab = m_table,
n_models = 3,
output = "kable"
)
class(mtab_kbl)[1] "kableExtra" "knitr_kable"
mtab_kbl| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
|---|---|---|---|---|---|---|---|---|---|
| (Intercept) | 0.54 | 0.46 – 0.63 | <0.001 | 0.01 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| Cell size | 5.11 | 3.87 – 6.73 | <0.001 | 2.10 | 1.55 – 2.83 | <0.001 | |||
| Cell shape [log] | 15.55 | 6.55 – 36.89 | <0.001 | ||||||
| Random Effects | |||||||||
| σ2 | 3.29 | 3.29 | 3.29 | ||||||
| τ00 | 0.00 city | 0.12 city | 0.00 city | ||||||
| ICC | 0.03 | ||||||||
| N | 7 city | 7 city | 7 city | ||||||
| Observations | 683 | 683 | 683 | ||||||
| Marginal $R^2$ / Conditional $R^2$ | 0.000 / NA | 0.880 / 0.884 | 0.861 / NA | ||||||
| AIC | 888.350 | 259.874 | 214.461 |