| Title: | Partial Eta-Squared for Crossed, Nested, and Mixed Linear Mixed Models |
|---|---|
| Description: | Computes partial eta-squared effect sizes for fixed effects in linear mixed models fitted with the 'lme4' package. Supports crossed, nested, and mixed (crossed-and-nested) random effects structures with any number of grouping factors. Mixed designs handle cases where grouping factors are simultaneously crossed with some variables and nested within others (e.g., photos nested within models, but both crossed with participants). Random slope variances are translated to the outcome scale using a variance decomposition approach, correctly accounting for predictor scaling and interaction terms. Both general and operative effect sizes are provided. Methods are based on Correll, Mellinger, McClelland, and Judd (2020) <doi:10.1016/j.tics.2019.12.009>, Correll, Mellinger, and Pedersen (2022) <doi:10.3758/s13428-021-01687-2>, and Rights and Sterba (2019) <doi:10.1037/met0000184>. |
| Authors: | Brandon Cohen [aut, cre] (ORCID: <https://orcid.org/0009-0004-1802-3435>), Joshua Correll [aut, ths] (ORCID: <https://orcid.org/0000-0003-1142-459X>) |
| Maintainer: | Brandon Cohen <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.2.0 |
| Built: | 2026-05-18 05:52:39 UTC |
| Source: | https://github.com/bcohen0901/pecanr |
Calculates partial eta-squared for all fixed effects (excluding the intercept) in a model.
batch_eta2p( model, data, design = c("crossed", "nested", "mixed"), subj_var = NULL, item_var = NULL, cross_vars = NULL, nest_vars = NULL, operative = FALSE, verbose = FALSE )batch_eta2p( model, data, design = c("crossed", "nested", "mixed"), subj_var = NULL, item_var = NULL, cross_vars = NULL, nest_vars = NULL, operative = FALSE, verbose = FALSE )
model |
A fitted model object from |
data |
Data frame used to fit the model. |
design |
Character string: |
subj_var |
Character string specifying the subject/participant grouping
variable. Retained for backward compatibility; prefer |
item_var |
Character string specifying the item/stimulus grouping
variable. Retained for backward compatibility; prefer |
cross_vars |
Character vector of grouping variable names that are
crossed with each other and with the nested hierarchy
(e.g., |
nest_vars |
Character vector of nesting variables ordered from lowest
to highest level (e.g., |
operative |
Logical. If |
verbose |
Logical. If |
A data frame with one row per effect containing:
effect |
Name of the fixed effect. |
eta2p |
Partial eta-squared value. |
effect_level |
Effect level (nested/mixed designs only). |
variance_effect |
Variance attributed to the effect. |
variance_error |
Error variance used in the denominator. |
type |
|
within_subj, within_item
|
(Crossed/mixed, operative only) Whether the effect is within subjects / within items. |
Rows are sorted by eta2p in decreasing order.
Calculates partial eta-squared effect sizes for fixed effects in linear mixed models with crossed, nested, or mixed (crossed-and-nested) random effects.
eta2p( model, effect, data, design = c("crossed", "nested", "mixed"), subj_var = NULL, item_var = NULL, cross_vars = NULL, nest_vars = NULL, effect_level = NULL, var_x = NULL, operative = FALSE, verbose = TRUE )eta2p( model, effect, data, design = c("crossed", "nested", "mixed"), subj_var = NULL, item_var = NULL, cross_vars = NULL, nest_vars = NULL, effect_level = NULL, var_x = NULL, operative = FALSE, verbose = TRUE )
model |
A fitted model object from |
effect |
Character string specifying the fixed effect to analyze.
Must match a name in |
data |
Data frame used to fit the model. |
design |
Character string: |
subj_var |
Character string specifying the subject/participant grouping
variable. Retained for backward compatibility; prefer |
item_var |
Character string specifying the item/stimulus grouping
variable. Retained for backward compatibility; prefer |
cross_vars |
Character vector of grouping variable names that are
crossed with each other and with the nested hierarchy
(e.g., |
nest_vars |
Character vector of nesting variables ordered from lowest
to highest level (e.g., |
effect_level |
Character string specifying the level at which the effect
varies (e.g., |
var_x |
Optional numeric. Pre-computed variance of the predictor (or
interaction product). If supplied, overrides the internal |
operative |
Logical. If |
verbose |
Logical. If |
The function implements a variance decomposition approach for computing partial eta-squared in mixed models. Random slope variances are translated to the outcome scale using:
For interaction effects, is computed as the variance of
the actual product term, correctly accounting for centering, scaling, and
predictor correlation. The var_x argument allows bypassing this
computation when the variance is known a priori.
For general effect sizes (default), all variance components appear
in the denominator. For operative effect sizes
(operative = TRUE), only components that contribute to the standard
error of the effect are included. In mixed designs, each grouping factor
(both crossed and nested) is independently classified as
"within" or "between" the focal effect; between-subjects
intercept variances are excluded from the operative denominator.
Use design = "mixed" when the model contains both crossed and nested
random effects simultaneously. A canonical example is participants viewing
multiple photos of each model (stimulus): photos are nested within models,
but both levels are crossed with participants.
The corresponding lme4 model and eta2p call would be:
fit <- lmer(y ~ x + (1 | participant) + (1 | model) + (1 | photo:model),
data = dat)
eta2p(fit, "x", dat,
design = "mixed",
cross_vars = "participant",
nest_vars = c("photo", "model"))
Residual variance is attributed to the crossed side and counted exactly once; the nested calculator's residual is subtracted to prevent double-counting.
Supports any number of grouping factors via cross_vars. The
two-argument form (subj_var + item_var) is retained for
backward compatibility and is equivalent to
cross_vars = c(subj_var, item_var).
An object of class "eta2p_lmm" containing:
eta2p |
Partial eta-squared value. |
variance_effect |
Variance explained by the effect. |
variance_error |
Error variance (denominator). |
effect |
Name of the effect. |
design |
Design type: |
operative |
Whether operative effect size was calculated. |
variance_components |
List of individual variance components. For
|
within_between |
(Mixed/crossed designs) Named list or vector
classifying each grouping factor as |
cross_vars |
(Crossed/mixed designs) Crossed grouping variable names. |
nest_vars |
(Nested/mixed designs) Nested grouping variable names. |
n_per_factor |
(Crossed designs) Number of units per crossed factor. |
n_cross |
(Mixed designs) Number of units per crossed factor. |
n_nested |
(Mixed designs) Number of units per nested factor. |
n_levels |
(Nested designs) Number of units per nested level. |
effect_level |
(Nested/mixed designs) Detected or supplied effect level. |
Correll, J., Mellinger, C., McClelland, G. H., & Judd, C. M. (2020). Avoid Cohen's 'Small', 'Medium', and 'Large' for Power Analysis. Trends in Cognitive Sciences, 24(3), 200–207. doi:10.1016/j.tics.2019.12.009
Correll, J., Mellinger, C., & Pedersen, E. J. (2022). Flexible approaches for estimating partial eta squared in mixed-effects models with crossed random factors. Behavior Research Methods, 54, 1626–1642. doi:10.3758/s13428-021-01687-2
Rights, J. D., & Sterba, S. K. (2019). Quantifying explained variance in multilevel models: An integrative framework for defining R-squared measures. Psychological Methods, 24(3), 309–338. doi:10.1037/met0000184
library(lme4) # --- Two crossed factors (backward-compatible call) --- set.seed(42) crossed_data <- data.frame( y = rnorm(120), condition = rep(c(-0.5, 0.5), 60), subject = factor(rep(1:20, each = 6)), item = factor(rep(1:6, 20)) ) model_c <- lmer(y ~ condition + (1 | subject) + (1 | item), data = crossed_data) eta2p(model_c, "condition", crossed_data, design = "crossed", subj_var = "subject", item_var = "item") # --- Three crossed factors using cross_vars --- set.seed(42) three_way_data <- data.frame( y = rnorm(180), condition = rep(c(-0.5, 0.5), 90), subject = factor(rep(1:20, each = 9)), item = factor(rep(rep(1:6, each = 3), 10)), rater = factor(rep(1:3, 60)) ) model_3 <- lmer(y ~ condition + (1 | subject) + (1 | item) + (1 | rater), data = three_way_data) eta2p(model_3, "condition", three_way_data, design = "crossed", cross_vars = c("subject", "item", "rater")) # --- Mixed design: photos nested within models, crossed with participants --- # Participants each view multiple photos of multiple models. # Photos are nested within models (each photo belongs to one model), # but both levels are crossed with participants. set.seed(42) n_subj <- 30; n_model <- 10; n_photo <- 3 mixed_data <- expand.grid( participant = factor(seq_len(n_subj)), photo_id = factor(seq_len(n_model * n_photo)) ) mixed_data$model_id <- factor( rep(seq_len(n_model), each = n_photo)[as.integer(mixed_data$photo_id)] ) mixed_data$x <- rnorm(nrow(mixed_data)) mixed_data$y <- rnorm(nrow(mixed_data)) model_m <- lmer(y ~ x + (1 | participant) + (1 | model_id) + (1 | photo_id:model_id), data = mixed_data) eta2p(model_m, "x", mixed_data, design = "mixed", cross_vars = "participant", nest_vars = c("photo_id", "model_id")) # --- Supply predictor variance directly (var_x) --- eta2p(model_c, "condition", crossed_data, design = "crossed", cross_vars = c("subject", "item"), var_x = 1) # +/-1 binary predictor: var = 1 by designlibrary(lme4) # --- Two crossed factors (backward-compatible call) --- set.seed(42) crossed_data <- data.frame( y = rnorm(120), condition = rep(c(-0.5, 0.5), 60), subject = factor(rep(1:20, each = 6)), item = factor(rep(1:6, 20)) ) model_c <- lmer(y ~ condition + (1 | subject) + (1 | item), data = crossed_data) eta2p(model_c, "condition", crossed_data, design = "crossed", subj_var = "subject", item_var = "item") # --- Three crossed factors using cross_vars --- set.seed(42) three_way_data <- data.frame( y = rnorm(180), condition = rep(c(-0.5, 0.5), 90), subject = factor(rep(1:20, each = 9)), item = factor(rep(rep(1:6, each = 3), 10)), rater = factor(rep(1:3, 60)) ) model_3 <- lmer(y ~ condition + (1 | subject) + (1 | item) + (1 | rater), data = three_way_data) eta2p(model_3, "condition", three_way_data, design = "crossed", cross_vars = c("subject", "item", "rater")) # --- Mixed design: photos nested within models, crossed with participants --- # Participants each view multiple photos of multiple models. # Photos are nested within models (each photo belongs to one model), # but both levels are crossed with participants. set.seed(42) n_subj <- 30; n_model <- 10; n_photo <- 3 mixed_data <- expand.grid( participant = factor(seq_len(n_subj)), photo_id = factor(seq_len(n_model * n_photo)) ) mixed_data$model_id <- factor( rep(seq_len(n_model), each = n_photo)[as.integer(mixed_data$photo_id)] ) mixed_data$x <- rnorm(nrow(mixed_data)) mixed_data$y <- rnorm(nrow(mixed_data)) model_m <- lmer(y ~ x + (1 | participant) + (1 | model_id) + (1 | photo_id:model_id), data = mixed_data) eta2p(model_m, "x", mixed_data, design = "mixed", cross_vars = "participant", nest_vars = c("photo_id", "model_id")) # --- Supply predictor variance directly (var_x) --- eta2p(model_c, "condition", crossed_data, design = "crossed", cross_vars = c("subject", "item"), var_x = 1) # +/-1 binary predictor: var = 1 by design