library(sjtable2df)
library(mlbench)
# load data
data("PimaIndiansDiabetes2")
dataset <- PimaIndiansDiabetes2 |>
data.table::as.data.table()
# create new binary variable
dataset[, ("preg_gt_4") := ifelse(get("pregnant") > 4, 1, 0) |> factor()]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("PimaIndiansDiabetes2")
dataset <- PimaIndiansDiabetes2 |>
data.table::as.data.table()
# create new binary variable
dataset[, ("preg_gt_4") := ifelse(get("pregnant") > 4, 1, 0) |> factor()]xtab <- sjPlot::tab_xtab(
var.row = dataset$diabetes,
var.col = dataset$preg_gt_4,
show.summary = TRUE,
use.viewer = FALSE
)xtab| diabetes | preg_gt_4 | Total | |
|---|---|---|---|
| 0 | 1 | ||
| neg | 356 | 144 | 500 |
| pos | 136 | 132 | 268 |
| Total | 492 | 276 | 768 |
| χ2=30.823 · df=1 · &phi=0.203 · p=0.000 | |||
data.framextab_df <- sjtable2df::xtab2df(xtab = xtab, output = "data.frame")
class(xtab_df)[1] "data.frame"
xtab_df diabetes preg_gt_4 0 preg_gt_4 1 Total
1 neg 356 144 500
2 pos 136 132 268
3 Total 492 276 768
4 χ2=30.823 · df=1 · &phi=0.203 · p=0.000
kablextab_kbl <- sjtable2df::xtab2df(
xtab = xtab,
output = "kable",
caption = "Diabetes vs. preg>4",
col.names = c("Diabetes", "No", "Yes", "Total")
)
class(xtab_kbl)[1] "kableExtra" "knitr_kable"
xtab_kbl |>
kableExtra::add_header_above(
header = c(" " = 1, "Pregnant > 4" = 2, " " = 1)
)| Diabetes | No | Yes | Total |
|---|---|---|---|
| neg | 356 | 144 | 500 |
| pos | 136 | 132 | 268 |
| Total | 492 | 276 | 768 |
| $χ2=30.823 · df=1 · &phi=0.203 · p=0.000$ |
This function also extracts further statistics from cells and writes them to parentheses:
xtab <- sjPlot::tab_xtab(
var.row = dataset$diabetes,
var.col = dataset$preg_gt_4,
show.summary = TRUE,
show.col.prc = TRUE,
use.viewer = FALSE
)xtab| diabetes | preg_gt_4 | Total | |
|---|---|---|---|
| 0 | 1 | ||
| neg | 356 72.4 % |
144 52.2 % |
500 65.1 % |
| pos | 136 27.6 % |
132 47.8 % |
268 34.9 % |
| Total | 492 100 % |
276 100 % |
768 100 % |
| χ2=30.823 · df=1 · &phi=0.203 · p=0.000 | |||
data.framextab_df <- sjtable2df::xtab2df(xtab = xtab, output = "data.frame")
xtab_df diabetes preg_gt_4 0 preg_gt_4 1 Total
1 neg 356 (72.4 %) 144 (52.2 %) 500 (65.1 %)
2 pos 136 (27.6 %) 132 (47.8 %) 268 (34.9 %)
3 Total 492 (100 %) 276 (100 %) 768 (100 %)
4 χ2=30.823 · df=1 · &phi=0.203 · p=0.000
m0 <- lm(
pressure ~ 1,
data = dataset
)
m1 <- lm(
pressure ~ glucose,
data = dataset
)
m2 <- lm(
pressure ~ glucose + diabetes,
data = dataset
)m_table <- sjPlot::tab_model(
m0,
m1,
m2,
show.aic = TRUE
)m_table| pressure | pressure | pressure | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Estimates | CI | p | Estimates | CI | p | Estimates | CI | p |
| (Intercept) | 72.41 | 71.51 – 73.30 | <0.001 | 61.46 | 57.85 – 65.06 | <0.001 | 62.65 | 58.85 – 66.44 | <0.001 |
| glucose | 0.09 | 0.06 – 0.12 | <0.001 | 0.07 | 0.04 – 0.11 | <0.001 | |||
| diabetes [pos] | 2.06 | -0.06 – 4.18 | 0.056 | ||||||
| Observations | 733 | 728 | 728 | ||||||
| R2 / R2 adjusted | 0.000 / 0.000 | 0.050 / 0.049 | 0.055 / 0.052 | ||||||
| AIC | 5771.995 | 5697.909 | 5696.248 | ||||||
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
1 (Intercept) 72.41 71.51 – 73.30 <0.001 61.46
2 glucose 0.09
3 diabetes [pos]
4 Observations 733 728
5 R2 / R2 adjusted 0.000 / 0.000 0.050 / 0.049
6 AIC 5771.995 5697.909
CI p Estimates CI p
1 57.85 – 65.06 <0.001 62.65 58.85 – 66.44 <0.001
2 0.06 – 0.12 <0.001 0.07 0.04 – 0.11 <0.001
3 2.06 -0.06 – 4.18 0.056
4 728
5 0.055 / 0.052
6 5696.248
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) | 72.41 | 71.51 – 73.30 | <0.001 | 61.46 | 57.85 – 65.06 | <0.001 | 62.65 | 58.85 – 66.44 | <0.001 |
| glucose | 0.09 | 0.06 – 0.12 | <0.001 | 0.07 | 0.04 – 0.11 | <0.001 | |||
| diabetes [pos] | 2.06 | -0.06 – 4.18 | 0.056 | ||||||
| Observations | 733 | 728 | 728 | ||||||
| $R^2$ / $R^2$ adjusted | 0.000 / 0.000 | 0.050 / 0.049 | 0.055 / 0.052 | ||||||
| AIC | 5771.995 | 5697.909 | 5696.248 |
m0 <- stats::glm(
diabetes ~ 1,
data = dataset,
family = binomial(link = "logit")
)
m1 <- stats::glm(
diabetes ~ glucose,
data = dataset,
family = binomial(link = "logit")
)
m2 <- stats::glm(
diabetes ~ glucose + pressure,
data = dataset,
family = binomial(link = "logit")
)m_table <- sjPlot::tab_model(
m0,
m1,
m2,
show.aic = TRUE
)m_table| diabetes | diabetes | diabetes | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
| (Intercept) | 0.54 | 0.46 – 0.62 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| glucose | 1.04 | 1.03 – 1.05 | <0.001 | 1.04 | 1.03 – 1.05 | <0.001 | |||
| pressure | 1.01 | 1.00 – 1.03 | 0.060 | ||||||
| Observations | 768 | 763 | 728 | ||||||
| R2 Tjur | 0.000 | 0.249 | 0.246 | ||||||
| AIC | 995.484 | 790.560 | 754.636 | ||||||
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.62 <0.001 0.00 0.00 – 0.01 <0.001
2 glucose 1.04 1.03 – 1.05 <0.001
3 pressure
4 Observations 768 763
5 R2 Tjur 0.000 0.249
6 AIC 995.484 790.560
Odds Ratios CI p
1 0.00 0.00 – 0.01 <0.001
2 1.04 1.03 – 1.05 <0.001
3 1.01 1.00 – 1.03 0.060
4 728
5 0.246
6 754.636
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.62 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| glucose | 1.04 | 1.03 – 1.05 | <0.001 | 1.04 | 1.03 – 1.05 | <0.001 | |||
| pressure | 1.01 | 1.00 – 1.03 | 0.060 | ||||||
| Observations | 768 | 763 | 728 | ||||||
| $R^2$ Tjur | 0.000 | 0.249 | 0.246 | ||||||
| AIC | 995.484 | 790.560 | 754.636 |
set.seed(1)
dataset$city <- sample(
x = paste0("city_", 1:7),
size = nrow(dataset),
replace = TRUE
)
m0 <- lme4::glmer(
diabetes ~ 1 + (1 | city),
data = dataset,
family = binomial(link = "logit")
)boundary (singular) fit: see help('isSingular')
m1 <- lme4::glmer(
diabetes ~ mass + (1 | city),
data = dataset,
family = binomial(link = "logit")
)
m2 <- lme4::glmer(
diabetes ~ mass + log(pressure) + (1 | city),
data = dataset,
family = binomial(link = "logit")
)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| diabetes | diabetes | diabetes | |||||||
|---|---|---|---|---|---|---|---|---|---|
| Predictors | Odds Ratios | CI | p | Odds Ratios | CI | p | Odds Ratios | CI | p |
| (Intercept) | 0.54 | 0.46 – 0.62 | <0.001 | 0.02 | 0.01 – 0.04 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| mass | 1.11 | 1.08 – 1.14 | <0.001 | 1.10 | 1.07 – 1.13 | <0.001 | |||
| pressure [log] | 3.31 | 1.26 – 8.67 | 0.015 | ||||||
| Random Effects | |||||||||
| σ2 | 3.29 | 3.29 | 3.29 | ||||||
| τ00 | 0.00 city | 0.01 city | 0.00 city | ||||||
| ICC | 0.00 | 0.00 | |||||||
| N | 7 city | 7 city | 7 city | ||||||
| Observations | 768 | 757 | 729 | ||||||
| Marginal R2 / Conditional R2 | 0.000 / NA | 0.133 / 0.135 | 0.137 / 0.137 | ||||||
| AIC | 997.484 | 910.822 | 871.890 | ||||||
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.62 <0.001 0.02
2 mass 1.11
3 pressure [log]
4 Random Effects
5 σ2 3.29 3.29
6 τ00 0.00 city 0.01 city
7 ICC 0.00
8 N 7 city 7 city
9 Observations 768 757
10 Marginal R2 / Conditional R2 0.000 / NA 0.133 / 0.135
11 AIC 997.484 910.822
CI p Odds Ratios CI p
1 0.01 – 0.04 <0.001 0.00 0.00 – 0.01 <0.001
2 1.08 – 1.14 <0.001 1.10 1.07 – 1.13 <0.001
3 3.31 1.26 – 8.67 0.015
4
5 3.29
6 0.00 city
7 0.00
8 7 city
9 729
10 0.137 / 0.137
11 871.890
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.62 | <0.001 | 0.02 | 0.01 – 0.04 | <0.001 | 0.00 | 0.00 – 0.01 | <0.001 |
| mass | 1.11 | 1.08 – 1.14 | <0.001 | 1.10 | 1.07 – 1.13 | <0.001 | |||
| pressure [log] | 3.31 | 1.26 – 8.67 | 0.015 | ||||||
| Random Effects | |||||||||
| σ2 | 3.29 | 3.29 | 3.29 | ||||||
| τ00 | 0.00 city | 0.01 city | 0.00 city | ||||||
| ICC | 0.00 | 0.00 | |||||||
| N | 7 city | 7 city | 7 city | ||||||
| Observations | 768 | 757 | 729 | ||||||
| Marginal $R^2$ / Conditional $R^2$ | 0.000 / NA | 0.133 / 0.135 | 0.137 / 0.137 | ||||||
| AIC | 997.484 | 910.822 | 871.890 |