sjtable2df: Overview

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.

Example: Contingency-Tables

Data Preprocessing

library(sjtable2df)
library(mlbench)

# load data
data("BreastCancer")
dataset <- BreastCancer |>
  data.table::as.data.table() |>
  na.omit()

Create Contingency Table

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

Convert Contingency Table to data.frame

xtab_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

Convert Contingency Table to kable

xtab_kbl <- sjtable2df::xtab2df(
  xtab = xtab,
  output = "kable",
  caption = "Class vs. Mitoses"
)
class(xtab_kbl)
[1] "kableExtra"  "knitr_kable"

Percentages in cells

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

Convert Contingency Table to data.frame

xtab_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

Example: Model Tables: Linear Regression

Create Three Models

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
)

Create Model Table

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

Convert Model Table to data.frame

mtab_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                   

Convert Model Table to kable

mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
mtab_kbl
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
$R^2$ / $R^2$ adjusted 0.000 / 0.000 0.823 / 0.823 0.840 / 0.840
AIC 3471.319 2290.389 2221.652

Example: Model Tables: Logistic Regression

Create Three Models

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

Create Model Table

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

Convert Model Table to data.frame

mtab_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                   

Convert Model Table to kable

mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
mtab_kbl
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
$R^2$ Tjur 0.000 0.756 0.812
AIC 886.350 271.586 227.110

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(
  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')

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

Convert Model Table to data.frame

mtab_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                    

Convert Model Table to kable

mtab_kbl <- sjtable2df::mtab2df(
  mtab = m_table,
  n_models = 3,
  output = "kable"
)
class(mtab_kbl)
[1] "kableExtra"  "knitr_kable"
mtab_kbl
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 $R^2$ / Conditional $R^2$ 0.000 / NA 0.880 / 0.884 0.861 / NA
AIC 888.350 259.874 214.461