modelbased icon indicating copy to clipboard operation
modelbased copied to clipboard

estimate_contrasts() doesn't follow contrast (i.e., categorical) coding scheme

Open rbcavanaugh opened this issue 2 months ago • 0 comments

It looks like estimate contrasts doesn't change the direction of the contrast when the categorical contrast coding scheme is only changed using something like contrasts(data$cat) <- c(1, 0); it requires the levels of the factor to be change explicitly. I'm not sure this is intended behavior.

library(tidyverse)
library(medicaldata)
library(easystats)
#> # Attaching packages: easystats 0.7.5 (red = needs update)
#> ✔ bayestestR  0.17.0   ✔ correlation 0.8.8 
#> ✖ datawizard  1.2.0    ✔ effectsize  1.0.1 
#> ✔ insight     1.4.2    ✔ modelbased  0.13.0
#> ✖ performance 0.15.1   ✔ parameters  0.28.2
#> ✔ report      0.6.1    ✔ see         0.12.0
#> 
#> Restart the R-Session and update packages with `easystats::easystats_update()`.
strep_data <- strep_tb

# default coding
contrasts(strep_data$arm)
#>              Control
#> Streptomycin       0
#> Control            1
m0 <- glm(improved ~ arm + baseline_condition, data = strep_data, family = "binomial") # model
model_parameters(m0) # results
#> Parameter                   | Log-Odds |      SE |           95% CI |     z |      p
#> ------------------------------------------------------------------------------------
#> (Intercept)                 |    20.40 | 1416.66 | [ -69.19,      ] |  0.01 | 0.989 
#> arm [Control]               |    -2.74 |    0.67 | [  -4.26, -1.56] | -4.09 | < .001
#> baseline condition [2_Fair] |   -18.14 | 1416.66 | [-375.70, 55.51] | -0.01 | 0.990 
#> baseline condition [3_Poor] |   -20.45 | 1416.66 | [       , 68.83] | -0.01 | 0.988
#> 
#> Uncertainty intervals (profile-likelihood) and p-values (two-tailed)
#>   computed using a Wald z-distribution approximation.
#> 
#> The model has a log- or logit-link. Consider using `exponentiate =
#>   TRUE` to interpret coefficients as ratios.
#>   
#> Some coefficients are very large, which may indicate issues with
#>   complete separation.
estimate_contrasts(m0, contrast = "arm") 
#> Marginal Contrasts Analysis
#> 
#> Level1  | Level2       | Difference |   SE |         95% CI |     z |      p
#> ----------------------------------------------------------------------------
#> Control | Streptomycin |      -0.32 | 0.05 | [-0.42, -0.21] | -5.83 | < .001
#> 
#> Variable predicted: improved
#> Predictors contrasted: arm
#> Predictors averaged: baseline_condition
#> p-values are uncorrected.
#> Contrasts are on the response-scale.

# set control as reference using contrasts
contrasts(strep_data$arm) <- c(1, 0)
contrasts(strep_data$arm)
#>              [,1]
#> Streptomycin    1
#> Control         0
m1 <- glm(improved ~ arm + baseline_condition, data = strep_data, family = "binomial") # model
model_parameters(m1) # results
#> Parameter                   | Log-Odds |      SE |          95% CI |     z |      p
#> -----------------------------------------------------------------------------------
#> (Intercept)                 |    17.65 | 1416.66 | [-58.87,      ] |  0.01 | 0.990 
#> arm [1]                     |     2.74 |    0.67 | [  1.56,  4.26] |  4.09 | < .001
#> baseline condition [2_Fair] |   -18.14 | 1416.66 | [      , 65.04] | -0.01 | 0.990 
#> baseline condition [3_Poor] |   -20.45 | 1416.66 | [      , 68.83] | -0.01 | 0.988
#> 
#> Uncertainty intervals (profile-likelihood) and p-values (two-tailed)
#>   computed using a Wald z-distribution approximation.
estimate_contrasts(m1, contrast = "arm") 
#> Marginal Contrasts Analysis
#> 
#> Level1  | Level2       | Difference |   SE |         95% CI |     z |      p
#> ----------------------------------------------------------------------------
#> Control | Streptomycin |      -0.32 | 0.05 | [-0.42, -0.21] | -5.83 | < .001
#> 
#> Variable predicted: improved
#> Predictors contrasted: arm
#> Predictors averaged: baseline_condition
#> p-values are uncorrected.
#> Contrasts are on the response-scale.

# set contral as reference using factor levels
strep_data$arm <- factor(strep_data$arm, levels = c("Control", "Streptomycin"))
contrasts(strep_data$arm)
#>              Streptomycin
#> Control                 0
#> Streptomycin            1
m2 <- glm(improved ~ arm + baseline_condition, data = strep_data, family = "binomial") # model
model_parameters(m2) # results
#> Parameter                   | Log-Odds |      SE |          95% CI |     z |      p
#> -----------------------------------------------------------------------------------
#> (Intercept)                 |    17.65 | 1416.66 | [-58.87,      ] |  0.01 | 0.990 
#> arm [Streptomycin]          |     2.74 |    0.67 | [  1.56,  4.26] |  4.09 | < .001
#> baseline condition [2_Fair] |   -18.14 | 1416.66 | [      , 65.04] | -0.01 | 0.990 
#> baseline condition [3_Poor] |   -20.45 | 1416.66 | [      , 68.83] | -0.01 | 0.988
#> 
#> Uncertainty intervals (profile-likelihood) and p-values (two-tailed)
#>   computed using a Wald z-distribution approximation.
estimate_contrasts(m2, contrast = "arm") 
#> Marginal Contrasts Analysis
#> 
#> Level1       | Level2  | Difference |   SE |       95% CI |    z |      p
#> -------------------------------------------------------------------------
#> Streptomycin | Control |       0.32 | 0.05 | [0.21, 0.42] | 5.83 | < .001
#> 
#> Variable predicted: improved
#> Predictors contrasted: arm
#> Predictors averaged: baseline_condition
#> p-values are uncorrected.
#> Contrasts are on the response-scale.

Created on 2025-10-23 with reprex v2.1.1

rbcavanaugh avatar Oct 23 '25 10:10 rbcavanaugh