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