tidymodels / tidymodels/multilevelmod
`predict()` ignores random effects by default in `glmer` engine
Nobody has claimed this yet.
- Dominant language
- R
- Stars
- 74
- Forks
- 6
- Avg merge
- 1h 53m
- Merged PRs (30d)
- 1
Description
The problem
The predict() method for multilevel models fitted with lme4 engines (i.e. lmer and glmer) in multilevelmod produces unexpected predictions that differ significantly from calling predict() directly on the underlying lme4 model object.
After investigation, I found this is because the prediction configuration hardcodes re.form = NA in make_lme4_logistic_reg(), which excludes random effects from predictions. With re.form = NA, predictions only use fixed effects, resulting in predictions that differ from the underlying model's default behavior.
Expected behaviour
Users should have control over whether random effects are included in predictions. There are valid use cases for both approaches:
- Population-level predictions (current behavior): For generalising to new groups not in the training data
- Conditional predictions (with random effects): For within-person or within-group predictions, accounting for individual/group-specific deviations
When analyzing longitudinal data or clustered observations, researchers often want predictions that account for individual-specific effects (e.g., predicting a specific person's outcome at a new timepoint). The current default forces population-level predictions, which may not be appropriate for all analyses.
Proposed Solution
I suggest one of the following approaches:
- Change the default to
re.form = NULL(which includes random effects, matching lme4's default behavior) - Add a parameter to
predict()that allows users to specifyre.form, similar to how it works in lme4 - Make it configurable through the parsnip workflow, allowing users to set this preference when creating the model specification
At the very least, users should be informed that this is the default behaviour. Thank you for considering this issue. I'm happy to provide additional details or testing if needed.
Reproducible example
library(multilevelmod)
#> Loading required package: parsnip
set.seed(1234)
data(sleepstudy, package = "lme4")
mixed_model_spec <- linear_reg() %>% set_engine("lmer")
mixed_model_fit <-
mixed_model_spec %>%
fit(Reaction ~ Days + (Days | Subject), data = sleepstudy)
# Without random effects by default
no_re <- predict(mixed_model_fit, sleepstudy)
# With random effects by calling lme4::predict() directly
with_re <- predict(extract_fit_engine(mixed_model_fit))
library(ggplot2)
data.frame(
no_re = no_re$.pred,
with_re = with_re
) |>
cbind(sleepstudy) |>
ggplot(aes(x = no_re, y = with_re)) +
geom_point() +
facet_wrap(vars(Subject))

Created on 2025-10-15 with reprex v2.1.1
Session info
sessioninfo::session_info()
#> Warning in system2("quarto", "-V", stdout = TRUE, env = paste0("TMPDIR=", :
#> running command '"quarto"
#> TMPDIR=C:/Users/u0134047/AppData/Local/Temp/RtmpK2Dzxu/fileb35456e02016 -V' had
#> status 1
#> ─ Session info ───────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.5.1 (2025-06-13 ucrt)
#> os Windows 11 x64 (build 26100)
#> system x86_64, mingw32
#> ui RTerm
#> language (EN)
#> collate Dutch_Netherlands.utf8
#> ctype Dutch_Netherlands.utf8
#> tz Europe/Brussels
#> date 2025-10-15
#> pandoc 3.6.3 @ c:\\Workdir\\MyApps\\Positron\\resources\\app\\quarto\\bin\\tools/ (via rmarkdown)
#> quarto NA @ C:\\Workdir\\MyApps\\RStudio\\RESOUR~1\\app\\bin\\quarto\\bin\\quarto.exe
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> boot 1.3-32 2025-08-29 [1] CRAN (R 4.5.1)
#> cli 3.6.5 2025-04-23 [1] CRAN (R 4.5.0)
#> curl 7.0.0 2025-08-19 [1] CRAN (R 4.5.1)
#> dichromat 2.0-0.1 2022-05-02 [1] CRAN (R 4.4.0)
#> digest 0.6.37 2024-08-19 [1] CRAN (R 4.4.1)
#> dplyr 1.1.4 2023-11-17 [1] CRAN (R 4.4.1)
#> evaluate 1.0.5 2025-08-27 [1] CRAN (R 4.5.1)
#> farver 2.1.2 2024-05-13 [1] CRAN (R 4.4.1)
#> fastmap 1.2.0 2024-05-15 [1] CRAN (R 4.4.1)
#> fs 1.6.6 2025-04-12 [1] CRAN (R 4.5.0)
#> generics 0.1.4 2025-05-09 [1] CRAN (R 4.5.0)
#> ggplot2 * 4.0.0 2025-09-11 [1] CRAN (R 4.5.1)
#> glue 1.8.0 2024-09-30 [1] CRAN (R 4.4.1)
#> gtable 0.3.6 2024-10-25 [1] CRAN (R 4.4.2)
#> hardhat 1.4.2 2025-08-20 [1] CRAN (R 4.5.1)
#> htmltools 0.5.8.1 2024-04-04 [1] CRAN (R 4.4.1)
#> knitr 1.50 2025-03-16 [1] CRAN (R 4.5.0)
#> labeling 0.4.3 2023-08-29 [1] CRAN (R 4.4.0)
#> lattice 0.22-7 2025-04-02 [1] CRAN (R 4.5.0)
#> lifecycle 1.0.4 2023-11-07 [1] CRAN (R 4.4.1)
#> lme4 1.1-37 2025-03-26 [1] CRAN (R 4.5.0)
#> magrittr 2.0.4 2025-09-12 [1] CRAN (R 4.5.1)
#> MASS 7.3-65 2025-02-28 [1] CRAN (R 4.5.0)
#> Matrix 1.7-4 2025-08-28 [1] CRAN (R 4.5.1)
#> minqa 1.2.8 2024-08-17 [1] CRAN (R 4.4.1)
#> multilevelmod * 1.0.0 2022-06-17 [1] CRAN (R 4.4.1)
#> nlme 3.1-168 2025-03-31 [1] CRAN (R 4.5.0)
#> nloptr 2.2.1 2025-03-17 [1] CRAN (R 4.5.0)
#> parsnip * 1.3.3 2025-08-31 [1] CRAN (R 4.5.1)
#> pillar 1.11.1 2025-09-17 [1] CRAN (R 4.5.1)
#> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.4.1)
#> purrr 1.1.0 2025-07-10 [1] CRAN (R 4.5.1)
#> R6 2.6.1 2025-02-15 [1] CRAN (R 4.4.2)
#> rbibutils 2.3 2024-10-04 [1] CRAN (R 4.4.1)
#> RColorBrewer 1.1-3 2022-04-03 [1] CRAN (R 4.4.0)
#> Rcpp 1.1.0 2025-07-02 [1] CRAN (R 4.5.1)
#> Rdpack 2.6.4 2025-04-09 [1] CRAN (R 4.5.0)
#> reformulas 0.4.1 2025-04-30 [1] CRAN (R 4.5.0)
#> reprex 2.1.1 2024-07-06 [1] CRAN (R 4.4.1)
#> rlang 1.1.6 2025-04-11 [1] CRAN (R 4.5.0)
#> rmarkdown 2.30 2025-09-28 [1] CRAN (R 4.5.1)
#> S7 0.2.0 2024-11-07 [1] CRAN (R 4.4.2)
#> scales 1.4.0 2025-04-24 [1] CRAN (R 4.5.0)
#> sessioninfo 1.2.3 2025-02-05 [1] CRAN (R 4.4.2)
#> sparsevctrs 0.3.4 2025-05-25 [1] CRAN (R 4.5.0)
#> tibble 3.3.0 2025-06-08 [1] CRAN (R 4.5.0)
#> tidyr 1.3.1 2024-01-24 [1] CRAN (R 4.4.1)
#> tidyselect 1.2.1 2024-03-11 [1] CRAN (R 4.4.1)
#> vctrs 0.6.5 2023-12-01 [1] CRAN (R 4.4.1)
#> withr 3.0.2 2024-10-28 [1] CRAN (R 4.4.2)
#> xfun 0.53 2025-08-19 [1] CRAN (R 4.5.1)
#> xml2 1.4.0 2025-08-20 [1] CRAN (R 4.5.1)
#> yaml 2.3.10 2024-07-26 [1] CRAN (R 4.4.1)
#>
#> [1] C:/Workdir/MyApps/R-Library/4.0
#> [2] C:/Workdir/MyApps/R/R-4.5.1/library
#> * ── Packages attached to the search path.
#>
#> ──────────────────────────────────────────────────────────────────────────────
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the discrepancy with the lmer and glmer examples, then inspect make_lme4_logistic_reg() where re.form = NA is hardcoded and compare it with lme4::predict() defaults. Done means the chosen behavior for random effects is implemented consistently, users can control it or are clearly informed, and predictions are covered for the affected engines.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- r
- Domain
- machine-learning
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100