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:
- https://stackoverflow.com/questions/63053465/how-to-convert-an-html-sjtable-from-the-sjplot-package-to-latex
- https://stackoverflow.com/questions/47744396/how-to-format-an-sjplot-in-pdf-rmarkdown
- https://stackoverflow.com/questions/62197268/knitting-output-from-sjplottab-model-or-other-html-tables-into-pdf-document
- https://stackoverflow.com/questions/65274404/how-to-extract-lme4-output-to-latex-tables
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.
Example: Contingency-Tables
Data Preprocessing
library(sjtable2df)
library(mlbench)
library(magrittr)
# 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()]
 
Create Contingency Table
xtab <- sjPlot::tab_xtab(
  var.row = dataset$diabetes,
  var.col = dataset$preg_gt_4,
  show.summary = TRUE,
  use.viewer = FALSE
)
 
 
 | 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 | 
 
Convert Contingency Table to data.frame
xtab_df <- sjtable2df::xtab2df(xtab = xtab, output = "data.frame")
class(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
 
 
Convert Contingency Table to kable
xtab_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 vs. preg>4
| 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$ |  |  |  | 
 
 
Percentages in cells
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
)
 
 
 | 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 | 
 
Convert Contingency Table to data.frame
xtab_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
 
 
Example: Model Tables: Linear Regression
Create Three Models
m0 <- lm(
  pressure ~ 1,
  data = dataset
)
m1 <- lm(
  pressure ~ glucose,
  data = dataset
)
m2 <- lm(
  pressure ~ glucose + diabetes,
  data = dataset
)
 
Create Model Table
m_table <- sjPlot::tab_model(
  m0, m1, m2,
  show.aic = TRUE
)
 
|  | 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 | 
Convert Model Table to data.frame
mtab_df <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "data.frame"
)
class(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                     
 
 
Convert Model Table to kable
mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
 
| 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 |  |  | 
 
 
Example: Model Tables: Logistic Regression
Create Three Models
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")
)
 
Create Model Table
m_table <- sjPlot::tab_model(
  m0, m1, m2,
  show.aic = TRUE
)
 
|  | 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 | 
Convert Model Table to data.frame
mtab_df <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "data.frame"
)
class(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                   
 
 
Convert Model Table to kable
mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
 
| 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 |  |  | 
 
 
Example: Model Tables: GLMM
Create Three Models
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")
)
 
Create Model Table
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')
 
 
|  | 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 | 0.00 | 
| N | 7 city | 7 city | 7 city | 
| Observations | 768 | 757 | 729 | 
| Marginal R2 / Conditional R2 | 0.000 / 0.000 | 0.133 / 0.135 | 0.137 / 0.137 | 
| AIC | 997.484 | 910.822 | 871.890 | 
Convert Model Table to data.frame
mtab_df <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "data.frame"
)
class(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                             0.00
8                             N        7 city                           7 city
9                  Observations           768                              757
10 Marginal R2 / Conditional R2 0.000 / 0.000                    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                   
 
 
Convert Model Table to kable
mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
 
| 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 |  |  | 0.00 |  |  | 
| N | 7 city |  |  | 7 city |  |  | 7 city |  |  | 
| Observations | 768 |  |  | 757 |  |  | 729 |  |  | 
| Marginal $R^2$ / Conditional $R^2$ | 0.000 / 0.000 |  |  | 0.133 / 0.135 |  |  | 0.137 / 0.137 |  |  | 
| AIC | 997.484 |  |  | 910.822 |  |  | 871.890 |  |  |