When estimating "contextual models" (i.e., models that contain level-1 predictors as well as their cluster means on level-2), the estimation of the fixed effects should be unaffected by the centering scheme (grand mean centering, cgm, vs. group mean centering, cwc), according to the (psychological) literature (see, e.g., Kreft et al., 1995, or Enders & Tofighi, 2007).
However, if I try this in R with lme4
, this is (numerically) true only if the models are specified without random slopes.
Moreover, the well-known relationship for the context effect (or its variants), $\gamma_{10}^{cgm}+\gamma_{01}^{cgm}=\gamma_{01}^{cwc}$, also only holds in this case (see, e.g., Enders & Tofighi, 2007).
Enders and Tofighi (2007) write: Because of a lack of precision in the estimation process, the algebraic identities outlined by Kreft et al. (1995) may not hold exactly when substituting the estimated parameter values into the equations outlined in this section.
My questions are:
- Why is this so?
- Why is the imprecision only there for models without random slopes?
- Which of the two is (cgm or cwc) is the "better" estimate?
Also note that the problem remains when using ML and not REML for estimation.
Example code (Example comes from here)
library(dplyr)
library(lme4)
AMIB <- read.csv(file = url("https://quantdev.ssri.psu.edu/sites/qdev/files/AMIBshare_daily_2019_0501.csv"), header = TRUE) %>%
select(id, negaff, pss) %>%
mutate(stress = 4 - pss) %>%
mutate(stress_trait = mean(stress, na.rm = TRUE), .by = id) %>%
mutate(stress_trait_c = stress_trait - mean(stress_trait)) %>%
mutate(stress_cgm = stress - mean(stress, na.rm = TRUE),
stress_cwc = stress - stress_trait)
ri_cgm <- lmer(negaff ~ stress_cgm + stress_trait_c + (1 | id), data = AMIB)
ri_cwc <- lmer(negaff ~ stress_cwc + stress_trait_c + (1 | id), data = AMIB)
fixef(ri_cgm)
sum(fixef(ri_cgm)[-1])
fixef(ri_cwc)
rs_cgm <- lmer(negaff ~ stress_cgm + stress_trait_c + (stress_cgm | id), data = AMIB)
rs_cwc <- lmer(negaff ~ stress_cwc + stress_trait_c + (stress_cwc | id), data = AMIB)
fixef(rs_cgm)
sum(fixef(rs_cgm)[-1])
fixef(rs_cwc)
Output:
> fixef(ri_cgm)
(Intercept) stress_cgm stress_trait_c
2.4567674 0.8429788 0.1996167
> sum(fixef(ri_cgm)[-1])
[1] 1.042596
> fixef(ri_cwc)
(Intercept) stress_cwc stress_trait_c
2.4587394 0.8429788 1.0425955
>
> fixef(rs_cgm)
(Intercept) stress_cgm stress_trait_c
2.4473444 0.7803662 0.2232565
> sum(fixef(rs_cgm)[-1])
[1] 1.003623
> fixef(rs_cwc)
(Intercept) stress_cwc stress_trait_c
2.459474 0.775756 1.019996
Literature
stress_trait
calculation is producing a single value applied to all ids. Instead, you need togroup_by
id and calculate a person mean:AMIB <- AMIB %>% group_by(id) %>% mutate(stress_pmn = mean(stress, na.rm = TRUE)) %>% ungroup()
$\endgroup$mutate(stress_trait = mean(stress, na.rm = TRUE), .by = id)
the argument.by = id
should take care of that, it's a shortcut such that we don't have to group/ungroup. $\endgroup$