The mlstats package provides tools for multilevel descriptive statistics and data preparation. It is designed for data where observations are nested within groups — for example, repeated daily measurements per person, students within classrooms, or employees within teams.
Example Data
To demonstrate, we use media_diary, a simulated daily
diary dataset included with mlstats. It mimics a study
in which 100 participants completed brief daily surveys for 14
consecutive days (N = 100 persons, T = 1,400 daily
observations). The variables are:
-
person: person identifier -
self_control: trait self-control, measured once at study entry (stable, between-person characteristic; ICC ≈ 1) -
wellbeing: daily positive wellbeing (1–7) -
screen_time: minutes of entertainment media consumed that day -
stress: daily perceived stress (1–7) -
enjoyment: enjoyment of the media watched that day (1–7)
data("media_diary")
media_diary
#> # A tibble: 1,400 × 6
#> person self_control wellbeing screen_time stress enjoyment
#> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
#> 1 1 5.1 4.9 80 4.1 5.7
#> 2 1 5.1 5.4 120 4 5.6
#> 3 1 5.1 5.8 98 3.4 5
#> 4 1 5.1 6.5 112 3.5 6.2
#> 5 1 5.1 5.5 21 2.8 4.4
#> 6 1 5.1 5.9 84 3.2 6
#> 7 1 5.1 6.4 48 2.6 5.1
#> 8 1 5.1 5.7 58 2.6 4.5
#> 9 1 5.1 6.5 39 2.4 5.3
#> 10 1 5.1 4.8 82 4 5.4
#> # ℹ 1,390 more rowsThe data are in long format: each row is one diary entry (one person
on one day). The person column identifies which person a
row belongs to.
Multilevel Descriptive Statistics
mldesc() produces a publication-ready descriptive
statistics table that combines means, standard deviations, ranges, ICCs,
and a within-/between-group correlation matrix in a single object:
vars <- c("self_control", "wellbeing", "screen_time", "stress")
result <- mldesc(
data = media_diary,
group = "person",
vars = vars
)
result
#> # Multilevel Descriptive Statistics
#> ============ ===== ====== ===== ===== ===== ===== ===== ===== =====
#> variable n_obs m sd range `1` `2` `3` `4` icc
#> ------------ ----- ------ ----- ----- ----- ----- ----- ----- -----
#> 1 Self control 1,400 4.03 0.83 2–6 – NA NA NA 1.00
#> 2 Wellbeing 1,400 4.45 0.87 2–7 .61* – .42* -.43* .46
#> 3 Screen time 1,400 128.66 42.29 0–272 -.67* -.34* – .29* .45
#> 4 Stress 1,400 3.81 0.91 1–7 -.53* -.38* .38* – .33
#> ============ ===== ====== ===== ===== ===== ===== ===== ===== =====
#> # ℹ Within-person correlations above, between-person correlations below the
#> # diagonal.
#> # ℹ All correlations marked with a star are significant at p < .05.
#> # ℹ Correlations estimated via variance decomposition.
#> # ℹ Group-weighted multilevel descriptive statistics computed with mlstats.Estimation Method
Three estimation methods are available via the method
argument:
-
method = "decomposition"(default): Uses the variance-decomposition approach to estimate within- and between-group correlations. Between-group correlations and descriptive statistics are weighted by group size whenweight = TRUE(the default). Setweight = FALSEto give every group equal influence. -
method = "sem": Fits a two-level structural equation model vialavaanusing robust maximum likelihood. This handles very unequal group sizes more rigorously. -
method = "bayes": Fits Bayesian multilevel models viabrms, reporting credible intervals instead of p-values. Requires the additionalciandfolderarguments; seevignette("multilevel-descriptives"). - See
vignette("correlation-methods")for a detailed comparison.
Customising the Output
Several options control the appearance of the output:
-
significance = "detailed": Adds stars for p < .05, p < .01, and p < .001. The default ("basic") marks only p < .05. -
flip = TRUE: Swaps the correlation matrix (between above, within below). -
remove_leading_zero = FALSE: Keeps the leading zero in decimal numbers. The default removes it for APA formatting (.45instead of0.45).
Pretty Printing
The result can be formatted for publication via print().
All print methods accept optional arguments table_title,
correlation_note, significance_note, and
note_text.
tinytable is included with mlstats (no extra installation needed):
result |>
print(format = "tt")| Descriptives | Correlationsa,b | ICC | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Variable | Nobs | M | SD | Range | 1 | 2 | 3 | 4 | ||
| Note. Group-weighted multilevel descriptive statistics computed with mlstats. | ||||||||||
| a Within-person correlations above, between-person correlations below the diagonal. | ||||||||||
| b All correlations marked with a star are significant at p < .05. | ||||||||||
| 1 | Self control | 1,400 | 4.03 | 0.83 | 2–6 | – | NA | NA | NA | 1.00 |
| 2 | Wellbeing | 1,400 | 4.45 | 0.87 | 2–7 | .61* | – | .42* | -.43* | .46 |
| 3 | Screen time | 1,400 | 128.66 | 42.29 | 0–272 | -.67* | -.34* | – | .29* | .45 |
| 4 | Stress | 1,400 | 3.81 | 0.91 | 1–7 | -.53* | -.38* | .38* | – | .33 |
If more customization is needed, gt produces richly formatted HTML tables. It must be installed separately:
install.packages("gt")
result |>
print(format = "gt")| Multilevel Descriptive Statistics | ||||||||||
| Variable |
Descriptives
|
Correlationsa,b
|
ICC
|
|||||||
|---|---|---|---|---|---|---|---|---|---|---|
| Nobs | M | SD | Range | 1 | 2 | 3 | 4 | |||
| 1 | Self control | 1,400 | 4.03 | 0.83 | 2–6 | – | NA | NA | NA | 1.00 |
| 2 | Wellbeing | 1,400 | 4.45 | 0.87 | 2–7 | .61* | – | .42* | -.43* | .46 |
| 3 | Screen time | 1,400 | 128.66 | 42.29 | 0–272 | -.67* | -.34* | – | .29* | .45 |
| 4 | Stress | 1,400 | 3.81 | 0.91 | 1–7 | -.53* | -.38* | .38* | – | .33 |
| Group-weighted multilevel descriptive statistics computed with mlstats. | ||||||||||
| a Within-person correlations above, between-person correlations below the diagonal. | ||||||||||
| b All correlations marked with a star are significant at p < .05. | ||||||||||
Both tt and gt smoothly render to HTML,
PDF, or Word via R Markdown or Quarto.
For details on customising printed tables — including custom titles,
notes, variable labels, and column selection — see
vignette("tables").
For detailed coverage of all mldesc() options and
within_between_correlations() (the underlying function),
including ICC and correlation matrix interpretation, see
vignette("multilevel-descriptives").
Decomposing Variables into Within- and Between-Person Components
Before fitting multilevel models, time-varying predictors are
typically decomposed into their within-group and between-group
components. decompose_within_between() makes this easy by
adding three new columns per variable:
-
_grand_mean_centered: grand-mean-centered value -
_between_{group}: group mean (stable between-group component) -
_within_{group}: deviation from the group mean (within-group fluctuation)
media_diary |>
decompose_within_between(
group = "person",
vars = c("stress", "screen_time")
) |>
select(starts_with("stress"))
#> # A tibble: 1,400 × 4
#> stress stress_grand_mean_centered stress_between_person stress_within_person
#> <dbl> <dbl> <dbl> <dbl>
#> 1 4.1 0.294 3.26 0.843
#> 2 4 0.194 3.26 0.743
#> 3 3.4 -0.406 3.26 0.143
#> 4 3.5 -0.306 3.26 0.243
#> 5 2.8 -1.01 3.26 -0.457
#> 6 3.2 -0.606 3.26 -0.0571
#> 7 2.6 -1.21 3.26 -0.657
#> 8 2.6 -1.21 3.26 -0.657
#> 9 2.4 -1.41 3.26 -0.857
#> 10 4 0.194 3.26 0.743
#> # ℹ 1,390 more rowsThe within and between components serve as separate predictors in
Random Effects Within-Between (REWB) models, which estimate distinct
within-group and between-group effects. See
vignette("rewb-models") for a full guide to data
preparation and REWB model fitting with mlstats, including all options
of decompose_within_between().
References
Bell, A., Fairbrother, M., & Jones, K. (2019). Fixed and random effects models: Making an informed choice. Quality & Quantity, 53(2), 1051–1074. https://doi.org/10.1007/s11135-018-0802-x
Enders, C. K., & Tofighi, D. (2007). Centering predictor variables in cross-sectional multilevel models: A new look at an old issue. Psychological Methods, 12(2), 121–138. https://doi.org/10.1037/1082-989X.12.2.121
Pedhazur, E. J. (1997). Multiple regression in behavioral research: Explanation and prediction (3rd ed.). Harcourt Brace.
