Getting Started with mlstats

library(mlstats)
library(dplyr)

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 were asked to complete a brief daily survey for up to 14 consecutive days; as in most real mobile diary studies, not everyone completed every day (N = 100 persons, T = 5–14 daily observations per person, 1,184 total). The variables are:

data("media_diary")
media_diary
#> # A tibble: 1,184 × 6
#>    person self_control wellbeing screen_time stress enjoyment
#>     <int>        <dbl>     <dbl>       <dbl>  <dbl>     <dbl>
#>  1      1            5       3.5          83    3.9       4.5
#>  2      1            5       4            82    4.4       3.9
#>  3      1            5       3.4         103    4.8       3.8
#>  4      1            5       3.7         105    4.7       4.6
#>  5      1            5       3.9          68    3.6       3.7
#>  6      1            5       4.3         143    5.3       5  
#>  7      1            5       5.3         139    2.9       5.4
#>  8      1            5       3.5         105    4.7       4.2
#>  9      1            5       3.1          75    3.7       3.9
#> 10      1            5       3.9          55    2.6       3.8
#> # ℹ 1,174 more rows

The 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   100   3.93  0.70 2.40–6.20     –    NA    NA    NA  1.00
#> 2 Wellbeing    1,184   4.42  0.89 1.50–7.00  .47*     –  .42* -.40*   .50
#> 3 Screen time  1,184 132.05 39.01    15–246 -.66* -.32*     –  .29*   .34
#> 4 Stress       1,184   3.77  0.95       1–7 -.55* -.27*  .46*     –   .39
#>   ============ ===== ====== ===== ========= ===== ===== ===== ===== =====
#> # ℹ Within-person correlations above, between-person correlations below the
#> #   diagonal.
#> # ℹ All correlations marked with a star are significant at p < .05.
#> # ℹ Based on 100 persons and 1,184 observations (median 12 per person; range:
#> #   5–14).
#> # ℹ Correlations estimated via variance decomposition.
#> # ℹ Group-weighted multilevel descriptive statistics computed with mlstats.

Estimation Method

Three estimation methods are available via the method argument:

Customising the Output

Several options control the appearance of the output:

Pretty Printing

The result can be formatted for publication via print(). All print methods accept optional arguments table_title, correlation_note, significance_note, group_size_note, and note_text.

tinytable is included with mlstats (no extra installation needed):

result |>
  print(format = "tt")
Multilevel Descriptive Statistics
Descriptives Correlationsa,b ICC
Variable Nobs M SD Range 1 2 3 4
Note. Group-weighted multilevel descriptive statistics computed with mlstats.
Based on 100 persons and 1,184 observations (median 12 per person; range: 5–14).
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 100 3.93 0.70 2.40–6.20 NA NA NA 1.00
2 Wellbeing 1,184 4.42 0.89 1.50–7.00 .47* .42* -.40* .50
3 Screen time 1,184 132.05 39.01 15–246 -.66* -.32* .29* .34
4 Stress 1,184 3.77 0.95 1–7 -.55* -.27* .46* .39

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 100 3.93 0.70 2.40–6.20 NA NA NA 1.00
2 Wellbeing 1,184 4.42 0.89 1.50–7.00 .47* .42* -.40* .50
3 Screen time 1,184 132.05 39.01 15–246 -.66* -.32* .29* .34
4 Stress 1,184 3.77 0.95 1–7 -.55* -.27* .46* .39
Group-weighted multilevel descriptive statistics computed with mlstats.
Based on 100 persons and 1,184 observations (median 12 per person; range: 5–14).
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, by default, two new columns per variable:

A third, optional column can be requested via components:

media_diary |>
  decompose_within_between(
    group = "person",
    vars  = c("stress", "screen_time")
  ) |>
  select(starts_with("stress"))
#> # A tibble: 1,184 × 3
#>    stress stress_between_person stress_within_person
#>     <dbl>                 <dbl>                <dbl>
#>  1    3.9                  4.12               -0.221
#>  2    4.4                  4.12                0.279
#>  3    4.8                  4.12                0.679
#>  4    4.7                  4.12                0.579
#>  5    3.6                  4.12               -0.521
#>  6    5.3                  4.12                1.18 
#>  7    2.9                  4.12               -1.22 
#>  8    4.7                  4.12                0.579
#>  9    3.7                  4.12               -0.421
#> 10    2.6                  4.12               -1.52 
#> # ℹ 1,174 more rows

The 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.