detect_facet_nesting: Detect nesting structure between facets

View source: R/api-hierarchical-audit.R

detect_facet_nestingR Documentation

Detect nesting structure between facets

Description

Classifies every ordered pair of facets (optionally including Person) as crossed, partially nested, near-perfectly nested, or fully nested, based on a conditional-entropy index:

\text{nesting\_index}(A \to B) = 1 - H(B \mid A) / H(B).

An index near 1 means that knowing the level of A essentially determines the level of B (A is nested in B).

Usage

detect_facet_nesting(data, facets, person = NULL, weight_col = NULL)

Arguments

data

Data frame in long format (one row per rating).

facets

Character vector of facet column names.

person

Optional name of the person column (adds Person to the nesting matrix if supplied).

weight_col

Optional name of a weight column; if supplied, rows are replicated proportionally when counting element co-occurrences.

Details

This is a pure descriptive review of the observed design. It does not affect estimation; fit_mfrm() continues to treat all facets as fixed effects.

Value

A list of class mfrm_facet_nesting with:

  • pairwise_table: one row per ordered facet pair with NestingIndex_AinB, NestingIndex_BinA, classification strings, and Direction.

  • summary: a one-line summary table with facet counts and whether any non-crossed structure was detected.

  • facets: the facet vector that was reviewed.

Classification bands

  • "Fully nested": nesting index >= 0.99.

  • "Near-perfectly nested": 0.95 <= index < 0.99.

  • "Partially nested": 0.50 <= index < 0.95.

  • "Crossed": index < 0.50.

The direction column records which facet is nested in which, or "crossed" when neither direction is above 0.95.

Interpreting output

A Direction value of "Rater nested in Region" means that every rater appears in exactly one region (or very close to it). For additive fixed-effects MFRM, this is a concern: the severity of a rater is confounded with region-level variance that the model cannot partition. Consider reporting the nesting direction explicitly and, when relevant, refitting without the nested facet or moving to a hierarchical estimation tool (e.g. lme4::lmer, brms, TAM) to separate the variance components.

Direction = "crossed" is the most common reading when both nesting indices are below 0.5; the two facets largely co-occur at multiple combinations, which is the setting Linacre (1989) assumed.

Typical workflow

  1. Call detect_facet_nesting(data, facets) before fitting.

  2. If any pair is flagged as nested or partially nested, review the numeric index and the LevelsA/LevelsB counts.

  3. For downstream reporting, use analyze_hierarchical_structure() to bundle this output with ICC and design-effect summaries, which build_mfrm_manifest() then records for reproducibility.

References

McEwen, M. R. (2018). The effects of incomplete rating designs on results from many-facets-Rasch model analyses (Doctoral thesis, Brigham Young University). https://scholarsarchive.byu.edu/etd/6689/

Linacre, J. M. (1989). Many-facet Rasch measurement. MESA Press.

See Also

facet_small_sample_review(), analyze_hierarchical_structure(), compute_facet_icc(), compute_facet_design_effect(), fit_mfrm() (see "Fixed effects assumption" in its details).

Examples

toy <- load_mfrmr_data("example_core")
nesting <- detect_facet_nesting(toy, c("Rater", "Criterion"))
summary(nesting)

# Synthetic example: raters fully nested within regions.
d <- data.frame(
  Person = rep(paste0("P", formatC(1:20, width = 2, flag = "0")),
               each = 6),
  Rater  = rep(paste0("R", 1:6), 20),
  Region = rep(rep(c("A", "A", "B", "B", "C", "C"), 20)),
  Score  = sample(0:4, 120, replace = TRUE),
  stringsAsFactors = FALSE
)
nest <- detect_facet_nesting(d, c("Rater", "Region"))
nest$pairwise_table[, c("FacetA", "FacetB",
                        "NestingIndex_AinB", "Direction")]

mfrmr documentation built on June 13, 2026, 1:07 a.m.