Tutorials › Generalized Linear Mixed Models (GLMM) › Extracting GLMM Results with broom.mixed

Software and Case Studies · Tutorial 666 of 698

Extracting GLMM Results with broom.mixed

Use broom.mixed to extract the right GLMM quantities and assemble a clearly labelled, publication-ready results table without confusing fixed effects with random effects.

Intermediate 10 min read

What You'll Learn

  • Select fixed effects, random-effect parameters, or cluster-level estimates with the effects argument.
  • Recognize common columns returned by broom.mixed::tidy() and what they represent.
  • Convert logistic-model coefficients and Wald intervals to conditional odds ratios.
  • Build a labelled table while preserving estimates, units, and inferential meaning.
  • Identify why tidy output does not replace model checks or justify unsupported p-values.

Why Extract Results With a Tidy Method?

A fitted GLMM object contains several kinds of results: population-level coefficients, estimated random-effect variation, and, when requested, cluster-specific random-effect estimates. They are not interchangeable. A table that reports a cluster-level estimate as though it were a population-level coefficient, or labels a standard deviation as a variance, can change the meaning of the analysis even when the numbers were extracted correctly.

The broom.mixed::tidy() function provides a structured way to request and organize these results. The goal is not merely to make a model output look neat. It is to select the intended quantity, retain the information needed to interpret it, and label the result precisely. The examples use a hypothetical logistic random-intercept model; the same distinction among result types applies to other GLMM families.

Definition: A tidy result is a rectangular data object in which each row represents a model term or parameter and columns hold its estimate and associated information. For a GLMM, broom.mixed::tidy() can return fixed effects, random-effect parameters, or conditional random-effect estimates. The effects argument specifies which type is requested.

Model and Extraction Assumptions

Suppose a binary outcome is observed for patients in clinics. Let \(Y_{ij}=1\) indicate improvement for patient \(i\) in clinic \(j\), let \(A_{ij}\) be age in years, and let \(T_{ij}\) indicate a treatment group. A logistic random-intercept GLMM can be written as

$$ Y_{ij}\mid b_j \sim \operatorname{Bernoulli}(p_{ij}),\qquad \operatorname{logit}(p_{ij})=\beta_0+\beta_T T_{ij}+\beta_A A_{ij}+b_j,\qquad b_j\sim N(0,\sigma_b^2). $$

This model assumes that, conditional on the clinic random intercept and the stated predictors, the outcomes follow the specified Bernoulli model; the clinic intercepts follow a mean-zero normal distribution with variance \(\sigma_b^2\); and the random intercepts are independent across clinics. The fixed-effect coefficients describe log-odds changes conditional on the random intercept. In particular, \(\exp(\beta_T)\) is a conditional odds ratio for treatment versus its reference group, holding age and the clinic intercept fixed.

Extraction does not establish that these assumptions are reasonable. It also does not remedy a failed fit. Before preparing a results table, check the model fit and the analysis choices that produced it, including convergence warnings, the intended reference categories, and whether the model formula matches the design. A tidy table is a presentation of model output, not an independent validation of the model.

For a fitted glmer object, the usual fixed-effect request is broom.mixed::tidy(fit, effects = "fixed"). Its rows represent fixed-effect terms; typical columns include term, estimate, std.error, statistic, and p.value. The exact available columns can depend on the model and method. Inspect the returned object before selecting columns, rather than assuming every model supplies every inferential quantity.

Worked Example: Extracting and Interpreting Fixed Effects

Assume a hypothetical model was fitted to 240 patients from 12 clinics. The coefficient output below is illustrative, not data from a real study. The fixed-effect estimates are an age coefficient of 0.030 with standard error 0.010, and a treatment coefficient of −0.400 with standard error 0.200. Treatment is coded 1 for the intervention and 0 for the reference group. For this example, suppose the fitted model passed its numerical convergence checks and the coding and model formula were verified.

Request the population-level terms with broom.mixed::tidy(fit, effects = "fixed"). The coefficient for age is on the log-odds scale. Its one-year conditional odds ratio is

$$ \exp(0.030)=1.030. $$

Thus, for two otherwise comparable patients in the same clinic, a one-year increase in age is associated with estimated odds of improvement multiplied by about 1.030, or approximately 3.0% higher odds. This is an odds comparison, not a 3.0 percentage-point change in probability.

A Wald 95% interval for the age coefficient is the estimate plus or minus 1.96 standard errors:

$$ 0.030\pm1.96(0.010)=[0.0104,\ 0.0496]. $$

Exponentiating both limits gives the conditional odds-ratio interval \([\exp(0.0104),\exp(0.0496)]\), approximately 1.010 to 1.051. In context, the interval describes values compatible with the fitted model and this interval procedure; it is not a 95% probability statement about the fixed parameter.

For treatment, the estimate is −0.400 on the log-odds scale, so the conditional odds ratio is \(\exp(-0.400)=0.670\). A Wald interval on the coefficient scale is

$$ -0.400\pm1.96(0.200)=[-0.792,\ -0.008]. $$

Exponentiating gives an odds-ratio interval of approximately \([\exp(-0.792),\exp(-0.008)]=[0.453,\ 0.992]\). The point estimate indicates lower estimated odds of improvement in the intervention group than the reference group, conditional on age and clinic intercept. This is an association under the model, not by itself evidence of a causal treatment effect.

Choosing Among Fixed and Random Effects

The effects argument controls which part of the fitted object is being tidied. For a mixed model, three useful requests have different interpretations:

RequestWhat the rows representTypical use
effects = "fixed"Population-level regression coefficientsReport adjusted associations or conditional odds ratios
effects = "ran_pars"Estimated random-effect variance, standard deviation, or correlation parametersDescribe the estimated spread of random effects
effects = "ran_vals"Estimated conditional random-effect values for grouping levelsInspect or report level-specific estimates when appropriate

For example, broom.mixed::tidy(fit, effects = "ran_pars", scales = "sdcor") requests random-effect parameters on standard-deviation/correlation scales. A random-intercept estimate of 0.50 in the estimate column is a standard deviation on the logit scale, not a variance and not a clinic-specific intercept. Its corresponding variance is \(0.50^2=0.25\) on the logit scale.

By contrast, effects = "ran_vals" requests estimated conditional random-effect values for particular grouping levels. These are often conditional modes or empirical Bayes estimates, not additional fixed coefficients and not directly observed clinic effects. Their estimates depend on the fitted model and are generally shrunk toward the population mean. If the scientific aim is a population-level comparison, these level-specific values do not replace the fixed-effect results.

Worked Example: Extracting a Random-Effect Standard Deviation

Suppose the hypothetical fit estimates the clinic random-intercept standard deviation as 0.50. Requesting broom.mixed::tidy(fit, effects = "ran_pars", scales = "sdcor") produces a row for the clinic random intercept, with an estimate of 0.50. The grouping variable and term identify what varies; check these labels in the returned data before presenting the result.

The standard deviation is measured in log-odds units because the clinic intercept enters the linear predictor. Squaring it gives the variance:

$$ \widehat{\sigma_b^2}=(0.50)^2=0.25. $$

A report should therefore say “the estimated clinic random-intercept standard deviation was 0.50 on the logit scale,” if that is the selected scale. It should not call 0.50 a variance. If variance is the intended quantity, request or calculate the variance scale and label it accordingly. Neither value is an odds ratio.

From Tidy Output to a Publication Table

A useful table is selective but not ambiguous. Keep the term name, estimate, standard error, and whichever inferential columns the model supports. For a logistic model, transformations for a conditional odds-ratio table should be applied to the fixed-effect estimates and their interval limits, not to standard errors or test statistics. A simple Wald interval can be calculated on the coefficient scale and then exponentiated:

$$ \left[\exp(\hat{\beta}-1.96SE),\ \exp(\hat{\beta}+1.96SE)\right]. $$

This interval uses a large-sample normal approximation for the coefficient estimate. It should be identified as a Wald interval, and it may be unreliable when estimates are poorly determined or the approximation is weak. Random-effect standard deviations require their own appropriate uncertainty method; do not apply the fixed-effect Wald formula to them automatically.

A practical workflow is to save the tidy output, inspect its column names and labels, select the fixed-effect rows, calculate any desired transformed estimates, and then assign reader-facing labels. For example, an R workflow can begin with fixed <- broom.mixed::tidy(fit, effects = "fixed"), followed by dplyr::select(fixed, term, estimate, std.error, statistic, p.value). If the table needs odds ratios and Wald limits, calculate those as new columns from estimate and std.error, and state the interval method in a table note. The symbol <- here is R's assignment operator.

The extracted term names may be machine-oriented, especially for factor contrasts and interactions. Replace them with explicit labels only after confirming the reference level and contrast coding. For example, “Treatment: intervention vs reference” is more informative than a bare factor name. Include units for continuous predictors, such as “Age, per year,” and state that odds ratios are conditional on the random effects. Avoid hiding the intercept or contrasts by filtering rows without a clear reporting reason.

Worked Example: Assembling a Labelled Odds-Ratio Table

Use the hypothetical estimates from the first example. For each fixed effect, calculate the conditional odds ratio by exponentiating the estimate and calculate Wald limits by exponentiating the estimate minus and plus 1.96 standard errors.

For age, the calculations are \(\exp(0.030)=1.030\), \(\exp(0.030-1.96(0.010))=\exp(0.0104)=1.010\), and \(\exp(0.030+1.96(0.010))=\exp(0.0496)=1.051\). The upper endpoint rounds to 1.051.

For treatment, the calculations are \(\exp(-0.400)=0.670\), \(\exp(-0.400-1.96(0.200))=\exp(-0.792)=0.453\), and \(\exp(-0.400+1.96(0.200))=\exp(-0.008)=0.992\).

Fixed effectConditional odds ratioWald 95% intervalInterpretation of unit or contrast
Age1.0301.010 to 1.051Per one-year increase
Treatment0.6700.453 to 0.992Intervention versus reference

A suitable table note would state that the estimates are conditional odds ratios from a logistic random-intercept GLMM, with Wald 95% intervals, adjusted for the listed predictors and conditional on the clinic random intercept. The table should not imply that its interval method was supplied by tidy() if the limits were calculated separately.

Derivation and Checks Before Reporting

The transformation used above follows directly from the logistic model. For a one-unit increase in a predictor with coefficient \(\beta\), holding the other predictors and random effect fixed, the log odds change from \(\eta\) to \(\eta+\beta\). Since odds are the exponential of log odds, the ratio of the new odds to the old odds is

$$ \frac{\exp(\eta+\beta)}{\exp(\eta)} =\exp(\beta). $$

For an approximate 95% coefficient interval \(\hat{\beta}\pm1.96SE\), exponentiation is valid because the exponential function is increasing: it preserves the order of the lower and upper limits. The resulting interval is therefore on the odds-ratio scale. The same calculation does not make a confidence interval exact, nor does it change the conditional interpretation of the coefficient.

Before exporting a table, verify that the selected rows are the intended effect type; that the grouping variable and term match the model; that standard deviations and variances are not mislabeled; and that transformed estimates and limits are calculated from the same coefficient and standard error. Check the model's convergence messages and whether a random-effect variance is estimated near zero. A singular fit or unstable estimates are reasons to investigate the fit, not reasons to suppress an inconvenient row.

For standard model output, summary(fit) is a direct alternative and is useful for checking what the fitted object reports. It is less convenient for consistent data-frame workflows. broom.mixed::tidy() makes selection and downstream table construction easier, but its flexibility creates opportunities to select the wrong effect or drop essential context. Neither approach decides which results are scientifically relevant or verifies the model assumptions. A publication table should also be checked against the model specification and the intended estimand.

Common Mistakes and Limitations

  • Treating all tidy rows as fixed effects. Random-effect parameters and level-specific estimates answer different questions. Select the intended type explicitly with effects.
  • Calling a standard deviation a variance. A random-intercept SD of 0.50 corresponds to variance 0.25; report the scale actually returned or calculated.
  • Exponentiating the standard error. For an odds-ratio interval, exponentiate coefficient limits. The standard error itself remains a measure on the coefficient scale.
  • Assuming a p-value is always available or decisive. Its presence and method depend on the fitted model and tidier. Report it only when supported, and do not interpret it as the probability that the null hypothesis is true.
  • Assuming tidy output means a successful analysis. Extraction does not diagnose convergence, singularity, poor coding, or model misspecification.

Tidy results are also not a complete record of an analysis. A table alone may omit the family, link, random-effects structure, reference categories, sample size, and interval method. Include enough model and table-note information for the reader to understand the reported estimand and reproduce the presentation choices.

Check Your Understanding

Answer each question, then compare your reasoning with the brief solutions.

  1. A fitted logistic GLMM returns an estimate of 0.40 for a fixed coefficient. What conditional odds ratio does it imply?
  2. A random-intercept standard deviation is estimated as 0.30. What is the corresponding variance, and what scale does the SD use in a logistic model?
  3. Why should a cluster-level estimate from effects = "ran_vals" not be presented as a population-level fixed-effect coefficient?
  4. For a coefficient estimate of 0.20 and standard error 0.10, calculate the Wald 95% interval on the coefficient scale and the exponentiated interval.

Solutions. (1) \(\exp(0.40)=1.492\), so the odds are estimated to be multiplied by about 1.492 for a one-unit predictor increase, conditional on the other model terms and random effect. (2) The variance is \(0.30^2=0.09\); the SD is on the logit scale. (3) It is a group-specific conditional random-effect estimate, not a shared regression coefficient describing the fixed population-level association. (4) The coefficient interval is \(0.20\pm1.96(0.10)=[0.004,0.396]\). Exponentiating the limits gives approximately \([1.004,1.486]\), a Wald interval for the conditional odds ratio.

Clinical Biostats