School effects
This example fits a linear mixed model to the 250 students from 12 schools in the school scores data. Test score depends on study hours, and each school has its own random intercept. The model estimates how much schools differ and how much of each school's apparent effect is noise.
The page compares the mixed model with a no-pooling model that gives every school a separate fixed intercept. The mixed model pulls each school's intercept toward the overall intercept, and it pulls schools with fewer students further.
Code
use function Phit\fit_lmer;
$scores = DataFrame::fromQuery(StudentScore::query());
$mixed = fit_lmer('score ~ study_hours + (1 | school)', $scores, reml: true);
$noPooling = $scores |> lm('score ~ 0 + school + study_hours');
$mixed['random'][0]['covariance']; // school variance
$mixed['random'][0]['effects']; // one random intercept per school
use function Phit\fit_lmer;
$scores = DataFrame::fromQuery(StudentScore::query());
$mixed = fit_lmer('score ~ study_hours + (1 | school)', $scores, reml: true);
$noPooling = phplyr($scores)->lm('score ~ 0 + school + study_hours');
$mixed['random'][0]['covariance']; // school variance
$mixed['random'][0]['effects']; // one random intercept per school
Phit\fit_lmer() takes the phibble DataFrame directly. Its results are verified against R's lme4.