Tables

Marginal effects

We can summarize the results of the comparisons() or slopes() functions using the modelsummary package.

library(modelsummary)
library(marginaleffects)
options(modelsummary_factory_default = "gt")

mod <- glm(am ~ wt + drat, family = binomial, data = mtcars)
mfx <- avg_slopes(mod)

modelsummary(mfx)
(1)
drat 0.278
(0.168)
wt -0.217
(0.080)
Num.Obs. 32
AIC 22.0
BIC 26.4
Log.Lik. -8.011
F 3.430
RMSE 0.28

The same results can be visualized with modelplot():

Contrasts

When using the comparisons() function (or the slopes() function with categorical variables), the output will include two columns to uniquely identify the quantities of interest: term and contrast.

dat <- mtcars
dat$gear <- as.factor(dat$gear)
mod <- glm(vs ~ gear + mpg, data = dat, family = binomial)

cmp <- comparisons(mod)
get_estimates(cmp)
#> # A tibble: 96 × 16
#>    rowid term  contrast estimate std.error statistic p.value s.value conf.low conf.high predicted_lo predicted_hi predicted    vs gear    mpg
#>    <int> <chr> <chr>       <dbl>     <dbl>     <dbl>   <dbl>   <dbl>    <dbl>     <dbl>        <dbl>        <dbl>     <dbl> <dbl> <fct> <dbl>
#>  1     1 gear  4 - 3      0.0736    0.264      0.279   0.780   0.358  -0.443      0.590       0.707        0.781     0.781      0 4      21  
#>  2     2 gear  4 - 3      0.0736    0.264      0.279   0.780   0.358  -0.443      0.590       0.707        0.781     0.781      0 4      21  
#>  3     3 gear  4 - 3      0.0321    0.125      0.257   0.797   0.327  -0.213      0.277       0.892        0.924     0.924      1 4      22.8
#>  4     4 gear  4 - 3      0.0636    0.231      0.275   0.783   0.352  -0.389      0.517       0.761        0.824     0.761      1 3      21.4
#>  5     5 gear  4 - 3      0.0913    0.324      0.282   0.778   0.362  -0.543      0.725       0.334        0.425     0.334      0 3      18.7
#>  6     6 gear  4 - 3      0.0796    0.288      0.276   0.782   0.354  -0.485      0.645       0.250        0.329     0.250      1 3      18.1
#>  7     7 gear  4 - 3      0.0111    0.0489     0.227   0.820   0.286  -0.0847     0.107       0.0242       0.0353    0.0242     0 3      14.3
#>  8     8 gear  4 - 3      0.0122    0.0517     0.236   0.813   0.298  -0.0891     0.114       0.961        0.973     0.973      1 4      24.4
#>  9     9 gear  4 - 3      0.0321    0.125      0.257   0.797   0.327  -0.213      0.277       0.892        0.924     0.924      1 4      22.8
#> 10    10 gear  4 - 3      0.0964    0.338      0.285   0.776   0.367  -0.566      0.759       0.414        0.510     0.510      1 4      19.2
#> # ℹ 86 more rows

We can use the shape argument of the modelsummary function to structure the table properly:

modelsummary(cmp, shape = term + contrast ~ model)
(1)
gear 4 - 3 32
32
5 - 3 32
32
mpg +1 32
32
Num.Obs. 32
AIC 26.2
BIC 32.1
Log.Lik. -9.101
F 2.389
RMSE 0.31

Cross-contrasts can be a bit trickier, since there are multiple simultaneous groups. Consider this example:

mod <- lm(mpg ~ factor(cyl) + factor(gear), data = mtcars)
cmp <- comparisons(
  mod,
  variables = c("gear", "cyl"),
  cross = TRUE)
get_estimates(cmp)
#> # A tibble: 128 × 17
#>    rowid term  contrast_cyl contrast_gear estimate std.error statistic p.value s.value conf.low conf.high predicted_lo predicted_hi predicted   mpg   cyl  gear
#>    <int> <chr> <chr>        <chr>            <dbl>     <dbl>     <dbl>   <dbl>   <dbl>    <dbl>     <dbl>        <dbl>        <dbl>     <dbl> <dbl> <dbl> <dbl>
#>  1     1 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      20.1  21       6     4
#>  2     2 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      20.1  21       6     4
#>  3     3 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      26.8  22.8     4     4
#>  4     4 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      18.8  21.4     6     3
#>  5     5 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      14.9  18.7     8     3
#>  6     6 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      18.8  18.1     6     3
#>  7     7 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      14.9  14.3     8     3
#>  8     8 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      26.8  24.4     4     4
#>  9     9 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      26.8  22.8     4     4
#> 10    10 cross 6 - 4        4 - 3            -5.33      2.77     -1.93  0.0542    4.21    -10.8    0.0953         25.4         20.1      20.1  19.2     6     4
#> # ℹ 118 more rows

As we can see above, there are two relevant grouping columns: contrast_gear and contrast_cyl. We can simply plug those names in the shape argument:

modelsummary(
  cmp,
  shape = contrast_gear + contrast_cyl ~ model)
gear cyl (1)
4 - 3 6 - 4 32
32
8 - 4 32
32
5 - 3 6 - 4 32
32
8 - 4 32
32
Num.Obs. 32
R2 0.740
R2 Adj. 0.701
AIC 173.7
BIC 182.5
Log.Lik. -80.838
F 19.190
RMSE 3.03