phit

Guides

Mixed models

fit_lmer() fits Gaussian linear mixed models, as lme4::lmer() does. fit_glmer() fits a binomial logit model with one random intercept, as lme4::glmer() does for that structure. Both take an R formula with lme4’s bar syntax for random effects.

Phit\fit_lmer(string $formula, array|object $data, bool $reml = true, string $missing = 'drop',
    array|string|null $weights = null, ?array $start = null, int $maxEvaluations = 20000,
    float $tolerance = 1e-7, string $optimizer = 'bobyqa', float $objectiveTolerance = 1e-12): array;
Phit\fit_glmer(string $formula, array|object $data, string $family = 'binomial', string $link = '',
    string $missing = 'drop', array|string|null $weights = null, int $quadraturePoints = 1,
    int $maxEvaluations = 20000, float $tolerance = 1e-7): array;

Supported structures

Function Random terms Family and link Fitting method
fit_lmer (1 | g), (x | g), (0 + x | g), (x || g) (uncorrelated), several terms such as (1 | g1) + (1 | g2), interaction groups (1 | g1:g2), and nesting (1 | g1/g2) Gaussian, identity REML (default) or ML (reml: false); BOBYQA (default) or Nelder–Mead (optimizer: 'nelder_mead')
fit_glmer Exactly one (1 | g) Binomial, logit ML by Laplace (quadraturePoints: 1, the default) or adaptive Gauss–Hermite quadrature with 2 to 61 points

Any other random-effect structure, family or link throws code 1007. Random slopes, several random terms, the Poisson and probit families, and REML are not available in fit_glmer(). Random-effect terms in fit_lm() or fit_glm() also throw code 1007.

A random-intercept model

The example uses docs/data/schools.csv from the repository: 250 simulated students in 12 schools, with study hours, a prior score and a test score.

use function Phit\{fit_lmer, read_csv};

$csv = read_csv('docs/data/schools.csv');
$schools = array_combine($csv['names'], array_column($csv['columns'], 'values'));

$fit = fit_lmer('score ~ study_hours + prior_score + (1 | school)', $schools);
foreach ($fit['columns'] as $i => $name) {
    printf("%-12s %8.4f %8.4f\n", $name, $fit['coefficients'][$i], $fit['std_errors'][$i]);
}
$school = $fit['random'][0];
printf("%s: school SD %.4f, residual SD %.4f, %d schools\n", $fit['method'],
    sqrt($school['covariance'][0][0]), $fit['sigma'], count($school['group_labels']));
printf("%s %+.4f\n", $school['group_labels'][0], $school['effects'][0][0]);
(Intercept)   46.6627   2.2438
study_hours    1.6141   0.1609
prior_score    0.2453   0.0419
REML: school SD 4.4579, residual SD 5.0566, 12 schools
school-01 +0.1353

school-01’s predicted random intercept is 0.14 points above the average school.

Reading a fit_lmer result

Key Contents
coefficients, std_errors, z_statistics, p_values, conf_int, covariance Fixed effects, with normal (Wald) tests and 95% intervals
random One entry per random term, in formula order
sigma, residual_variance Residual standard deviation and variance
theta Relative covariance factors, as lme4’s getME(fit, "theta")
log_likelihood, aic, bic, n_parameters The REML criterion or the ML log-likelihood, according to method
fitted, fixed_fitted, residuals, marginal_residuals Conditional and fixed-effects-only predictions and residuals
method, optimizer, evaluations, converged, singular Fitting details

Each random entry has label, group, columns and correlated, the term’s covariance matrix, effects (one row of conditional modes per group), effects_cond_var (one k×k conditional covariance per group, lme4’s ranef(condVar = TRUE)), group_labels and group_sizes. Groups are ordered by first appearance after missing-value deletion. lme4 sorts them instead. The estimates do not depend on the order.

The fixed-effect tests use the normal distribution. lme4 reports t values without p-values, and packages such as lmerTest add degrees-of-freedom approximations. phit has no degrees-of-freedom correction.

Singular fits

A random-effect variance estimated at or near zero, or a correlation at ±1, makes the covariance singular. The fit returns with singular true and the warning random-effect covariance is singular or near singular in diagnostics.warnings. With these data, score ~ study_hours + (1 + study_hours | school) is singular: the slope variance is about 0.001. A singular fit usually means the random-effect structure is more complex than the data support.

A binomial random-intercept model

docs/data/cbpp.csv holds lme4’s cbpp data: cases of contagious bovine pleuropneumonia in 15 herds over four periods.

use function Phit\{fit_glmer, read_csv};

$csv = read_csv('docs/data/cbpp.csv', ['types' => ['c', 'i', 'i', 'c']]);
$herds = array_combine($csv['names'], array_column($csv['columns'], 'values'));
$herds['healthy'] = array_map(fn ($n, $k) => $n - $k, $herds['size'], $herds['incidence']);

$fit = fit_glmer('cbind(incidence, healthy) ~ period + (1 | herd)', $herds, quadraturePoints: 10);
foreach ($fit['named'] as $name => $b) printf("%-12s %8.4f\n", $name, $b);
printf("herd SD %.4f, %s\n", $fit['random_intercept_sd'], $fit['integration']);
(Intercept)   -1.3992
period2       -0.9914
period3       -1.1278
period4       -1.5795
herd SD 0.6475, adaptive_gauss_hermite

quadraturePoints is lme4’s nAGQ. The Laplace default is fastest. More points approximate the likelihood more closely, which matters most for small groups and rare events. No number of points guarantees accuracy for every data set, so compare a few values when the estimates matter.

A fit_glmer result reports the herd effects directly: random_effects, random_effects_cond_var, group_labels, group_sizes, n_groups, random_intercept_variance and random_intercept_sd. It also has linear_predictor, neg2_log_likelihood, quadrature_points, integration, gradient_max and boundary, and the fixed-effect keys of fit_lmer.

Prediction

predict() adds each known group’s random effects by default, as lme4’s re.form = NULL does. random: false predicts at the population level, and the grouping columns can then be absent. A group the fit never saw throws code 1001 unless allowNewLevels: true, which predicts it at the population level. Mixed-model predictions have no standard errors, as in lme4.

Matrix functions

fit_mixed(), fit_mixed_intercept() and fit_logistic_mixed() fit the same models from numeric matrices and explicit random-effect designs. fit_mixed_intercept() is a faster path for a Gaussian random intercept by ML. Matrix model functions defines their inputs, the optimizer controls and the convergence rules.

From phpstats/phit@76b22f0.