| Title: | Hierarchical Linear Modeling with Visualization and Decomposition |
|---|---|
| Description: | Provides functions for visualization and decomposition in hierarchical linear models (HLM) for applications in education, psychology, and the social sciences. Includes variance decomposition for two-level and three-level data structures following Snijders and Bosker (2012, ISBN:9781849202015), intraclass correlation (ICC) estimation and design effect computation as described in Shrout and Fleiss (1979) <doi:10.1037/0033-2909.86.2.420>, and contextual effect decomposition via the Mundlak (1978) <doi:10.2307/1913646> specification distinguishing within- and between-cluster components, with the uncertainty of the contextual contrast obtained from the full fixed-effect covariance matrix. Teaching displays cover simulated intraclass correlations, partial pooling of cluster means, random-slope heterogeneity, and cross-level interaction with an observed Level-2 moderator, following Hofmann and Gavin (1998) <doi:10.1177/014920639802400504> and Hamaker and Muthen (2020) <doi:10.1037/met0000239>. Multilevel models are estimated using 'lme4' (Bates et al., 2015 <doi:10.18637/jss.v067.i01>). An optional 'Shiny' application enables interactive exploration of model components and parameter variation. The implementation follows the multilevel modeling framework of Raudenbush and Bryk (2002, ISBN:9780761919049). |
| Authors: | Subir Hait [aut, cre] (ORCID: <https://orcid.org/0009-0004-9871-9677>) |
| Maintainer: | Subir Hait <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0.9000 |
| Built: | 2026-09-28 22:20:31 UTC |
| Source: | https://github.com/subirhait/hlmlab |
Given a multilevel model containing a within-cluster centered predictor and its cluster-mean counterpart (Mundlak specification), this function extracts the within- and between-cluster effects and computes the contextual effect (between minus within) together with its standard error and a confidence interval.
hlm_context(model, x_within, x_between, level = 0.95, check_centering = TRUE)hlm_context(model, x_within, x_between, level = 0.95, check_centering = TRUE)
model |
A fitted |
x_within |
Name of the within-cluster centered predictor (string). |
x_between |
Name of the cluster-mean predictor (string). |
level |
Confidence level for the reported intervals. Defaults to 0.95. |
check_centering |
Logical; if |
The contextual effect is a linear contrast of two fixed-effect coefficients, so its sampling variance is
Since version 0.2.0 the covariance term is taken from the fixed-effect
covariance matrix returned by stats::vcov() rather than assumed to be
zero. In a random-intercept model with an exactly group-mean centered
x_within, that covariance is zero by construction, so results are
unchanged; it is generally nonzero when the model contains a random slope,
when x_within is centered in some other way, or when the Mundlak
specification uses the raw (uncentered) predictor.
Intervals use a normal approximation, which is the usual convention for
lme4 fixed effects because no denominator degrees of freedom are
supplied.
An object of class hlm_context, which is a tibble with:
effect_type |
Within, between, or contextual. |
estimate |
Estimate of the effect. |
se |
Standard error; exact for the contextual contrast. |
conf_low |
Lower confidence limit. |
conf_high |
Upper confidence limit. |
The covariance of the two coefficients is stored in the attribute
"cov_within_between" and the confidence level in "level".
Mundlak, Y. (1978). On the pooling of time series and cross section data. Econometrica, 46, 69-85. doi:10.2307/1913646
# Build a small toy dataset (no external data needed) set.seed(1) n_schools <- 8 n_students <- 12 school_id <- rep(seq_len(n_schools), each = n_students) SES_raw <- rnorm(n_schools * n_students) SES_mean <- rep(tapply(SES_raw, school_id, mean), each = n_students) SES_c <- SES_raw - SES_mean math_score <- 50 + 2 * SES_c + 3 * SES_mean + rep(rnorm(n_schools, sd = 2), each = n_students) + rnorm(n_schools * n_students) toy <- data.frame(math_score = math_score, SES_c = SES_c, SES_mean = SES_mean, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + SES_mean + (1 | school_id), data = toy) ctx <- hlm_context(m, x_within = "SES_c", x_between = "SES_mean") ctx hlm_context_plot(ctx)# Build a small toy dataset (no external data needed) set.seed(1) n_schools <- 8 n_students <- 12 school_id <- rep(seq_len(n_schools), each = n_students) SES_raw <- rnorm(n_schools * n_students) SES_mean <- rep(tapply(SES_raw, school_id, mean), each = n_students) SES_c <- SES_raw - SES_mean math_score <- 50 + 2 * SES_c + 3 * SES_mean + rep(rnorm(n_schools, sd = 2), each = n_students) + rnorm(n_schools * n_students) toy <- data.frame(math_score = math_score, SES_c = SES_c, SES_mean = SES_mean, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + SES_mean + (1 | school_id), data = toy) ctx <- hlm_context(m, x_within = "SES_c", x_between = "SES_mean") ctx hlm_context_plot(ctx)
Convenience wrapper to plot contextual effects
hlm_context_plot(object)hlm_context_plot(object)
object |
An object of class |
A ggplot object.
set.seed(1) school_id <- rep(seq_len(8), each = 12) SES_raw <- rnorm(96) SES_mean <- rep(tapply(SES_raw, school_id, mean), each = 12) SES_c <- SES_raw - SES_mean math_score <- 50 + 2 * SES_c + 3 * SES_mean + rep(rnorm(8, sd = 2), each = 12) + rnorm(96) toy <- data.frame(math_score = math_score, SES_c = SES_c, SES_mean = SES_mean, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + SES_mean + (1 | school_id), data = toy) hlm_context_plot(hlm_context(m, "SES_c", "SES_mean"))set.seed(1) school_id <- rep(seq_len(8), each = 12) SES_raw <- rnorm(96) SES_mean <- rep(tapply(SES_raw, school_id, mean), each = 12) SES_c <- SES_raw - SES_mean math_score <- 50 + 2 * SES_c + 3 * SES_mean + rep(rnorm(8, sd = 2), each = 12) + rnorm(96) toy <- data.frame(math_score = math_score, SES_c = SES_c, SES_mean = SES_mean, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + SES_mean + (1 | school_id), data = toy) hlm_context_plot(hlm_context(m, "SES_c", "SES_mean"))
Plots the fitted Level-1 association at selected values of an observed
Level-2 moderator. Unlike hlm_random_slope_plot, which shows
unexplained slope heterogeneity, this display shows moderation by a measured
cluster characteristic, which is what the term cross-level interaction
denotes.
hlm_cross_level_plot( model, x_within, moderator, at = NULL, labels = NULL, n_points = 40, x_range = NULL, title = NULL, subtitle = NULL )hlm_cross_level_plot( model, x_within, moderator, at = NULL, labels = NULL, n_points = 40, x_range = NULL, title = NULL, subtitle = NULL )
model |
A fitted |
x_within |
Name of the Level-1 predictor (string). |
moderator |
Name of the Level-2 moderator (string). May be numeric or a factor. |
at |
Optional values of the moderator at which lines are drawn. For a numeric moderator the default is the mean and one standard deviation on either side; for a factor the default is every level. |
labels |
Optional character labels for the moderator values, used in the legend. |
n_points |
Number of points along the x-axis. Defaults to 40. |
x_range |
Optional length-2 numeric vector giving the plotting range of
|
title, subtitle
|
Optional plot title and subtitle. |
Fitted values are obtained from predict() with the random effects
excluded, so the lines describe the average cluster at each moderator value.
Remaining numeric predictors are held at their sample means and remaining
categorical predictors at their most frequent level. Variables must appear
in the model formula under their own names; inline transformations such as
log(x) are not supported.
A ggplot object. The plotted line data are attached as the
attribute "data".
set.seed(7) n_schools <- 20 n_students <- 20 school_id <- rep(seq_len(n_schools), each = n_students) school_resources <- rep(rnorm(n_schools), each = n_students) SES_c <- rnorm(n_schools * n_students) math_score <- 50 + 2 * SES_c + 1.5 * school_resources + 0.8 * SES_c * school_resources + rep(rnorm(n_schools, sd = 1), each = n_students) + rnorm(n_schools * n_students) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_resources = school_resources, school_id = school_id) m <- lme4::lmer( math_score ~ SES_c * school_resources + (1 | school_id), data = toy ) hlm_cross_level_plot(m, x_within = "SES_c", moderator = "school_resources")set.seed(7) n_schools <- 20 n_students <- 20 school_id <- rep(seq_len(n_schools), each = n_students) school_resources <- rep(rnorm(n_schools), each = n_students) SES_c <- rnorm(n_schools * n_students) math_score <- 50 + 2 * SES_c + 1.5 * school_resources + 0.8 * SES_c * school_resources + rep(rnorm(n_schools, sd = 1), each = n_students) + rnorm(n_schools * n_students) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_resources = school_resources, school_id = school_id) m <- lme4::lmer( math_score ~ SES_c * school_resources + (1 | school_id), data = toy ) hlm_cross_level_plot(m, x_within = "SES_c", moderator = "school_resources")
Decomposes a continuous variable into between-cluster, and within-cluster components (2-level), or into between-cluster (B), between-person (P), and within-person (W) components for longitudinal 3-level data.
hlm_decompose(data, var, cluster, id = NULL, time = NULL)hlm_decompose(data, var, cluster, id = NULL, time = NULL)
data |
A data frame. |
var |
Name of the focal variable (string). |
cluster |
Name of the cluster ID variable (e.g., school/classroom). |
id |
Optional person ID variable for longitudinal data. |
time |
Optional time variable (not required for the algebra, but noted in the output for clarity). |
This is primarily a teaching tool: it shows how total variance is partitioned across levels.
An object of class hlm_decompose with components:
data |
Original data with added decomposition columns. |
summary |
A tibble summarizing variance components and shares. |
# 2-level example (students in schools) set.seed(2) toy <- data.frame( math_score = rnorm(80, mean = 50, sd = 10), school_id = rep(letters[1:8], each = 10) ) hlm_decompose(toy, var = "math_score", cluster = "school_id") # 3-level longitudinal example (waves within students within schools) toy3 <- data.frame( math_score = rnorm(120, 50, 10), school_id = rep(letters[1:4], each = 30), student_id = rep(seq_len(24), each = 5) ) hlm_decompose(toy3, var = "math_score", cluster = "school_id", id = "student_id", time = NULL)# 2-level example (students in schools) set.seed(2) toy <- data.frame( math_score = rnorm(80, mean = 50, sd = 10), school_id = rep(letters[1:8], each = 10) ) hlm_decompose(toy, var = "math_score", cluster = "school_id") # 3-level longitudinal example (waves within students within schools) toy3 <- data.frame( math_score = rnorm(120, 50, 10), school_id = rep(letters[1:4], each = 30), student_id = rep(seq_len(24), each = 5) ) hlm_decompose(toy3, var = "math_score", cluster = "school_id", id = "student_id", time = NULL)
Convenience wrapper around hlm_decompose() for 3-level data:
clusters (e.g., schools), persons within clusters, and repeated measures
within persons over time.
hlm_decompose_long(data, var, cluster, id, time = NULL)hlm_decompose_long(data, var, cluster, id, time = NULL)
data |
A data frame. |
var |
Name of the focal variable (string). |
cluster |
Cluster ID (e.g., school/classroom) (string). |
id |
Person ID within cluster (string). |
time |
Optional time variable (string); stored in the output for reference but not required for the algebra. |
An object of class hlm_decompose with between-cluster (B),
between-person (P), and within-person (W) variance components and shares.
set.seed(4) toy_long <- data.frame( math_score = rnorm(120, 50, 10), school_id = rep(letters[1:4], each = 30), student_id = rep(seq_len(24), each = 5), wave = rep(seq_len(5), times = 24) ) hlm_decompose_long(data = toy_long, var = "math_score", cluster = "school_id", id = "student_id", time = "wave")set.seed(4) toy_long <- data.frame( math_score = rnorm(120, 50, 10), school_id = rep(letters[1:4], each = 30), student_id = rep(seq_len(24), each = 5), wave = rep(seq_len(5), times = 24) ) hlm_decompose_long(data = toy_long, var = "math_score", cluster = "school_id", id = "student_id", time = "wave")
Computes the intraclass correlation (ICC) and, optionally, a design effect
from a random-intercept multilevel model fitted with lme4::lmer().
hlm_icc(model, cluster_size = NULL)hlm_icc(model, cluster_size = NULL)
model |
A fitted |
cluster_size |
Optional. A scalar average cluster size used to compute
the design effect, or the string |
The ICC is a model-based share of variance, not a causal statement about
clusters and not a fixed property of a population. With
cluster_size = "auto" the observed cluster sizes are taken from the
model frame and two design effects are reported: the familiar
using the mean cluster size, and an unequal-size
version that replaces with . The
second is the more appropriate teaching approximation when cluster sizes
vary, and both are approximations rather than substitutes for fitting and
diagnosing a multilevel model.
An object of class hlm_icc with components:
icc |
Estimated intraclass correlation. |
deff |
Design effect based on the supplied or mean cluster size. |
deff_unequal |
Design effect adjusted for unequal cluster sizes
(only when |
re_var |
Random intercept variance. |
resid_var |
Residual variance. |
n_clusters |
Number of clusters (when available). |
mean_cluster_size |
Mean cluster size (when available). |
set.seed(3) toy <- data.frame( math_score = rnorm(80, 50, 10), SES = rnorm(80), school_id = rep(seq_len(8), each = 10) ) m <- lme4::lmer(math_score ~ SES + (1 | school_id), data = toy) hlm_icc(m, cluster_size = 10) hlm_icc(m, cluster_size = "auto")set.seed(3) toy <- data.frame( math_score = rnorm(80, 50, 10), SES = rnorm(80), school_id = rep(seq_len(8), each = 10) ) m <- lme4::lmer(math_score ~ SES + (1 | school_id), data = toy) hlm_icc(m, cluster_size = 10) hlm_icc(m, cluster_size = "auto")
Simulates clustered data at several target intraclass correlations, holding the total variance and the overall mean fixed, and displays them side by side. The figure is a teaching device: it shows that the ICC is a share of variance rather than a test of whether clustering exists, and that the same outcome scale can look very different at different ICC values.
hlm_icc_demo( icc = c(0.05, 0.25, 0.6), n_clusters = 12, cluster_size = 20, grand_mean = 50, total_sd = 10, exact = TRUE, seed = NULL, show_cluster_means = TRUE, sort_clusters = TRUE )hlm_icc_demo( icc = c(0.05, 0.25, 0.6), n_clusters = 12, cluster_size = 20, grand_mean = 50, total_sd = 10, exact = TRUE, seed = NULL, show_cluster_means = TRUE, sort_clusters = TRUE )
icc |
Numeric vector of target intraclass correlations, each strictly
between 0 and 1. Defaults to |
n_clusters |
Number of clusters per panel. Defaults to 12. |
cluster_size |
Number of observations per cluster. Defaults to 20. |
grand_mean |
Overall mean of the simulated outcome. Defaults to 50. |
total_sd |
Total standard deviation of the simulated outcome, held constant across panels. Defaults to 10. |
exact |
Logical; rescale the simulated components so that their
realized sample standard deviations match the targets, making the
data-generating ICC exactly the value in each panel label. Defaults to
|
seed |
Optional integer seed. When supplied, the state of the random number generator is restored on exit. |
show_cluster_means |
Logical; draw a horizontal marker at each cluster
mean. Defaults to |
sort_clusters |
Logical; order the clusters within each panel by their
mean. Defaults to |
For each target value the between-cluster standard deviation is
and the within-cluster standard
deviation is . With
exact = TRUE the simulated cluster effects and residuals are rescaled
so that their realized sample standard deviations match those targets, so
each panel is generated at exactly the ICC in its label.
That is a statement about the data-generating values, not about what a model fitted to one panel will report. An estimated ICC carries estimation error, and that error is proportionally largest where the ICC is small: with a dozen clusters and a target of 0.05, the between-cluster variance is of the same order as the sampling variance of a cluster mean, and a single fitted panel can easily return 0.03 or 0.08. The panel labels are therefore the values used to generate the data. Fitting a model to the attached data is a useful follow-up exercise, but the estimate should be expected to differ.
A ggplot object. The simulated data are attached as the attribute
"data".
hlm_icc_demo(icc = c(0.05, 0.25, 0.60), n_clusters = 8, cluster_size = 15, seed = 2026)hlm_icc_demo(icc = c(0.05, 0.25, 0.60), n_clusters = 8, cluster_size = 15, seed = 2026)
Visualizes the intraclass correlation by plotting the between- and within-cluster variance components as a stacked bar. This is intended as a teaching diagram to help students see how the ICC reflects the share of variance that lies between clusters.
hlm_icc_plot(model, cluster_size = NULL, labels = TRUE)hlm_icc_plot(model, cluster_size = NULL, labels = TRUE)
model |
A fitted |
cluster_size |
Optional scalar giving the average cluster size, or
|
labels |
Logical; print the component labels and percentages inside the
bar. Defaults to |
A ggplot object.
set.seed(3) toy <- data.frame( math_score = rnorm(80, 50, 10), school_id = rep(seq_len(8), each = 10) ) m0 <- lme4::lmer(math_score ~ 1 + (1 | school_id), data = toy) hlm_icc_plot(m0, cluster_size = "auto")set.seed(3) toy <- data.frame( math_score = rnorm(80, 50, 10), school_id = rep(seq_len(8), each = 10) ) m0 <- lme4::lmer(math_score ~ 1 + (1 | school_id), data = toy) hlm_icc_plot(m0, cluster_size = "auto")
Draws one fitted line per cluster from a model containing a random slope, together with the average fitted line. The display communicates unexplained heterogeneity in a Level-1 association across clusters.
hlm_random_slope_plot( model, x_within, cluster, n_points = 40, n_clusters = 20, select = c("spread", "random", "all"), x_range = NULL, hold_other = c("mean", "zero"), show_average = TRUE, title = NULL, subtitle = NULL )hlm_random_slope_plot( model, x_within, cluster, n_points = 40, n_clusters = 20, select = c("spread", "random", "all"), x_range = NULL, hold_other = c("mean", "zero"), show_average = TRUE, title = NULL, subtitle = NULL )
model |
A fitted |
x_within |
Name of the Level-1 predictor with a random slope (string). |
cluster |
Name of the clustering factor (string). |
n_points |
Number of points along the x-axis. Defaults to 40. |
n_clusters |
Maximum number of clusters to display. Defaults to 20. |
select |
How clusters are chosen when there are more than
|
x_range |
Optional length-2 numeric vector giving the plotting range of
|
hold_other |
Either |
show_average |
Logical; draw the average fitted line. Defaults to
|
title, subtitle
|
Optional plot title and subtitle. |
A random slope is not a cross-level interaction. It shows that the Level-1
association varies across clusters without saying why. A cross-level
interaction requires an observed Level-2 moderator; see
hlm_cross_level_plot.
All fixed-effect columns other than the intercept and x_within are
held at their sample means when hold_other = "mean", so the lines are
plotted on the scale of the observed outcome. Cluster-specific intercepts
and slopes are conditional (empirical Bayes) quantities and are already
shrunken toward the average; they should not be treated as precise rankings
of individual clusters.
A ggplot object. The plotted line data are attached as the
attribute "data".
hlm_cross_level_plot, hlm_shrinkage_plot
set.seed(42) n_schools <- 10 n_students <- 15 school_id <- rep(seq_len(n_schools), each = n_students) SES_c <- rnorm(n_schools * n_students) u0 <- rep(rnorm(n_schools, sd = 0.5), each = n_students) u1 <- rep(rnorm(n_schools, sd = 0.3), each = n_students) math_score <- 50 + 2 * SES_c + u0 + u1 * SES_c + rnorm(n_schools * n_students, sd = 1) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + (SES_c | school_id), data = toy) hlm_random_slope_plot(m, x_within = "SES_c", cluster = "school_id")set.seed(42) n_schools <- 10 n_students <- 15 school_id <- rep(seq_len(n_schools), each = n_students) SES_c <- rnorm(n_schools * n_students) u0 <- rep(rnorm(n_schools, sd = 0.5), each = n_students) u1 <- rep(rnorm(n_schools, sd = 0.3), each = n_students) math_score <- 50 + 2 * SES_c + u0 + u1 * SES_c + rnorm(n_schools * n_students, sd = 1) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + (SES_c | school_id), data = toy) hlm_random_slope_plot(m, x_within = "SES_c", cluster = "school_id")
Compares each cluster's raw mean with its multilevel (empirical Bayes) estimate and draws an arrow between them. The figure makes partial pooling visible: small clusters are pulled further toward the overall mean than large clusters, and extreme raw means are moderated most.
hlm_shrinkage_plot( model, n_clusters = 25, select = c("spread", "random", "all"), style = c("arrows", "size"), title = NULL, subtitle = NULL )hlm_shrinkage_plot( model, n_clusters = 25, select = c("spread", "random", "all"), style = c("arrows", "size"), title = NULL, subtitle = NULL )
model |
A fitted |
n_clusters |
Maximum number of clusters to display. Defaults to 25. |
select |
How clusters are chosen when there are more than
|
style |
|
title, subtitle
|
Optional plot title and subtitle. |
The multilevel estimate for cluster is
, which for an unconditional random-intercept
model equals with
reliability . The
comparison is interpretable in that unconditional case; a warning is issued
when the model contains additional fixed effects, because a raw cluster mean
and an adjusted intercept are then no longer the same quantity.
A ggplot object. A data frame with the raw mean, multilevel
estimate, cluster size, and reliability for every displayed cluster is
attached as the attribute "data".
set.seed(11) cluster_size <- sample(3:40, 25, replace = TRUE) school_id <- rep(seq_along(cluster_size), times = cluster_size) u0 <- rep(rnorm(length(cluster_size), sd = 5), times = cluster_size) math_score <- 50 + u0 + rnorm(length(school_id), sd = 10) toy <- data.frame(math_score = math_score, school_id = school_id) m0 <- lme4::lmer(math_score ~ 1 + (1 | school_id), data = toy) hlm_shrinkage_plot(m0)set.seed(11) cluster_size <- sample(3:40, 25, replace = TRUE) school_id <- rep(seq_along(cluster_size), times = cluster_size) u0 <- rep(rnorm(length(cluster_size), sd = 5), times = cluster_size) math_score <- 50 + u0 + rnorm(length(school_id), sd = 10) toy <- data.frame(math_score = math_score, school_id = school_id) m0 <- lme4::lmer(math_score ~ 1 + (1 | school_id), data = toy) hlm_shrinkage_plot(m0)
Deprecated in hlmLab 0.2.0. The display produced by this function shows
random-slope heterogeneity, which is not the same thing as a cross-level
interaction, so the function was renamed. Use
hlm_random_slope_plot instead; use
hlm_cross_level_plot when the model contains an observed
Level-2 moderator.
hlm_xint_geom(model, x_within, cluster, n_points = 20, n_clusters = 20)hlm_xint_geom(model, x_within, cluster, n_points = 20, n_clusters = 20)
model |
A fitted |
x_within |
Name of the Level-1 predictor with a random slope (string). |
cluster |
Name of the clustering factor (string). |
n_points |
Number of points to plot along the x-axis. Defaults to 20. |
n_clusters |
Maximum number of clusters to display (sampled). |
A ggplot object, produced by hlm_random_slope_plot.
set.seed(42) school_id <- rep(seq_len(10), each = 15) SES_c <- rnorm(150) u0 <- rep(rnorm(10, sd = 0.5), each = 15) u1 <- rep(rnorm(10, sd = 0.3), each = 15) math_score <- 50 + 2 * SES_c + u0 + u1 * SES_c + rnorm(150, sd = 1) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + (SES_c | school_id), data = toy) suppressWarnings( hlm_xint_geom(m, x_within = "SES_c", cluster = "school_id") )set.seed(42) school_id <- rep(seq_len(10), each = 15) SES_c <- rnorm(150) u0 <- rep(rnorm(10, sd = 0.5), each = 15) u1 <- rep(rnorm(10, sd = 0.3), each = 15) math_score <- 50 + 2 * SES_c + u0 + u1 * SES_c + rnorm(150, sd = 1) toy <- data.frame(math_score = math_score, SES_c = SES_c, school_id = school_id) m <- lme4::lmer(math_score ~ SES_c + (SES_c | school_id), data = toy) suppressWarnings( hlm_xint_geom(m, x_within = "SES_c", cluster = "school_id") )
Produces an error-bar plot of within, between, and contextual effects with confidence intervals. Intended as a teaching diagram.
## S3 method for class 'hlm_context' plot(x, ...)## S3 method for class 'hlm_context' plot(x, ...)
x |
An object of class |
... |
Not used. |
A ggplot object.
Produces a simple bar chart of variance shares across components, suitable for teaching how variance is partitioned across levels.
## S3 method for class 'hlm_decompose' plot(x, ...)## S3 method for class 'hlm_decompose' plot(x, ...)
x |
An object of class |
... |
Not used. |
A ggplot object.