
hlmLab provides tools for visualization and
decomposition in hierarchical linear models (HLM), designed for
researchers and students in education, psychology, and the social
sciences. It offers a coherent set of functions for understanding how
variance is distributed across levels, how predictors operate within and
between clusters, and how random slopes vary across groups — all built
on top of lme4.
Install the released version from CRAN:
install.packages("hlmLab")Or install the development version from GitHub:
# install.packages("remotes")
remotes::install_github("causalfragility-lab/hlmLab")| Function | What it does |
|---|---|
hlm_decompose() |
Decomposes variance into within- and between-cluster components (2-level or 3-level) |
hlm_decompose_long() |
Convenience wrapper for 3-level longitudinal B-P-W decomposition |
hlm_icc() |
Computes the intraclass correlation (ICC) and design effect from a fitted model |
hlm_icc_plot() |
Visualizes ICC as a stacked variance-partitioning bar chart |
hlm_context() |
Extracts within-cluster, between-cluster, and contextual effects (Mundlak specification) |
hlm_context_plot() |
Plots within, between, and contextual effects with 95% confidence intervals |
hlm_xint_geom() |
Produces a fan plot of random slopes to illustrate cross-level interactions |
hlm_decompose() partitions the total variance of a
continuous variable into between-cluster and within-cluster components
without fitting a model — useful as a first diagnostic step.
library(hlmLab)
# 2-level: students nested in schools
result <- hlm_decompose(data = mydata,
var = "math_score",
cluster = "school_id")
result
#> HLM variance decomposition for: math_score
#> # A tibble: 3 × 3
#> component variance share
#> <chr> <dbl> <dbl>
#> 1 Between clusters (B) 42.1 0.312
#> 2 Within clusters (W) 92.8 0.688
#> 3 Total 134.9 1.000
plot(result)For 3-level longitudinal data (students measured repeatedly within schools):
result_long <- hlm_decompose_long(data = mydata_long,
var = "math_score",
cluster = "school_id",
id = "student_id",
time = "wave")
plot(result_long)The plot shows a bar chart of variance shares across Between-cluster (B), Between-person (P), and Within-person (W) components.
hlm_icc() computes the ICC from a fitted
lme4 random-intercept model. Supplying
cluster_size also returns the design effect, which
quantifies how much clustering inflates standard errors relative to
simple random sampling.
library(lme4)
m0 <- lmer(math_score ~ 1 + (1 | school_id), data = mydata)
hlm_icc(m0, cluster_size = 25)
#> Intraclass correlation (ICC) and design effect
#> ICC : 0.312
#> RE variance : 42.1
#> Residual var. : 92.8
#> Design effect : 8.48Visualize the ICC as a variance-partitioning diagram:
hlm_icc_plot(m0, cluster_size = 25)The plot displays a horizontal stacked bar with between- and within-cluster variance shares, with the ICC and design effect shown in the subtitle.
hlm_context() separates the total effect of a Level-1
predictor into its within-cluster component (the pure individual-level
effect) and its between-cluster component (the group-level effect). The
contextual effect is their difference (between − within), following
Mundlak (1978).
The model must include both the within-cluster centered predictor and the cluster mean:
# Center SES within schools and compute school means
mydata$SES_c <- mydata$SES - ave(mydata$SES, mydata$school_id)
mydata$SES_mean <- ave(mydata$SES, mydata$school_id)
m1 <- lmer(math_score ~ SES_c + SES_mean + (1 | school_id),
data = mydata)
ctx <- hlm_context(m1,
x_within = "SES_c",
x_between = "SES_mean")
ctx
#> Contextual effect decomposition
#> effect_type estimate se
#> Within-cluster 2.31 0.18
#> Between-cluster 5.84 0.62
#> Contextual (B - W) 3.53 0.65Plot the three effects with 95% confidence intervals:
hlm_context_plot(ctx)
# or equivalently:
plot(ctx)hlm_xint_geom() visualizes how a random slope varies
across clusters, producing a fan plot where each line represents one
cluster’s predicted regression of the outcome on the Level-1 predictor.
Spread in the fan indicates slope heterogeneity; a cross-level
interaction moderates this spread.
m2 <- lmer(math_score ~ SES_c + SES_mean + (SES_c | school_id),
data = mydata)
hlm_xint_geom(m2,
x_within = "SES_c",
cluster = "school_id",
n_clusters = 20)Use n_clusters to limit the number of lines displayed
when you have many groups.
hlmLab implements methods from the following foundational references:
If you use hlmLab in your research, please cite it:
citation("hlmLab")Hait S (2025). hlmLab: Hierarchical Linear Modeling with Visualization
and Decomposition. R package version 0.1.0.
https://github.com/causalfragility-lab/hlmLab
Bug reports and feature requests are welcome at the issue tracker. Please include a minimal reproducible example with any bug report.
MIT © Subir Hait