RMdimCFA: Observed one-factor CFA fit and loadings vs a simulated...

View source: R/cfa_cutoff.R

RMdimCFAR Documentation

Observed one-factor CFA fit and loadings vs a simulated reference

Description

Fits the observed one-factor categorical CFA to data and compares its fit indices and per-item standardized loadings against the simulated null distribution produced by RMdimCFACutoff. Returns a list of two tables: model-fit indices and per-item loadings, each with the observed value, the expected reference from the simulation, and a flag.

Usage

RMdimCFA(
  data,
  cutoff,
  p_value = FALSE,
  correction = c("fwer", "fdr_bh", "fdr_by", "none"),
  alpha = 0.05,
  output = c("kable", "dataframe")
)

Arguments

data

A data.frame or matrix of item responses (non-negative integers, 0-based), the same items used for the cutoff simulation.

cutoff

The list returned by RMdimCFACutoff. Required: observed CFA fit indices are not interpretable without the simulated reference, so the function errors if it is missing.

p_value

Logical. When TRUE, adds bootstrap p-values from the simulated null distributions: one-sided in the unfavourable direction for the fit indices (CFI low; RMSEA / SRMR high), two-sided for the per-item loadings. The Flagged columns then reflect padj < alpha instead of the percentile cutoffs. The fit indices and the loadings are corrected as two separate families. Default FALSE.

correction

Character. Multiplicity correction for the p-values: "fwer" (default; Westfall-Young studentised-max step-down), "fdr_bh" (Benjamini-Hochberg), "fdr_by" (Benjamini-Yekutieli), or "none". Ignored when p_value = FALSE.

alpha

Numeric in (0, 1). Significance level used to flag comparisons on the corrected p-value. Default 0.05. Ignored when p_value = FALSE.

output

Character. "kable" (default) returns each table as a knitr::kable(); "dataframe" returns plain data.frames.

Details

Bootstrap p-values. The per-comparison statistic is the residual studentised by the bootstrap mean and SD. Marginal p-values are Monte-Carlo, (1 + count) / (B + 1), so they can be no smaller than 1 / (B + 1). correction = "fwer" uses the Westfall-Young studentised-max step-down, which exploits the bootstrap dependence among the statistics (Ferreira, 2024); it is liberal when the simulation is small, so at least 1000 iterations in RMdimCFACutoff() are recommended (a warning is issued below that). These p-values are model-conditional and sample-size-sensitive and are reported alongside the simulated expected ranges, not in place of them.

Value

A named list with two elements, fit and loadings:

fit

CFI / RMSEA / SRMR with columns Index, Observed, Cutoff, Direction, Flagged (one-sided, in the unfavourable direction). With p_value = TRUE, columns p and padj are added and Flagged reflects padj < alpha.

loadings

One row per item with columns Item, Observed, Expected_low, Expected_high, Flagged ("below" / "above" / ""). With p_value = TRUE, columns p_loading and padj_loading are added and Flagged reflects padj_loading < alpha (direction from the sign of the deviation from the simulated mean).

Each element is a knitr_kable (when output = "kable") or a data.frame (when output = "dataframe").

Multiple comparisons

The marginal p-value controls the error rate of a single comparison: for one item (or item pair) decided on in advance it is the relevant value. But scanning all k comparisons and flagging whichever fall below alpha tests k hypotheses at once, so the chance of at least one false flag inflates to roughly 1 - (1 - \alpha)^k (e.g. about 34% for k = 8 at alpha = 0.05) – even when every marginal p-value is correctly calibrated. The corrected (adjusted) p-value controls this: correction = "fwer" bounds the probability of any false flag (strict, lower power), while "fdr_bh" / "fdr_by" bound the expected proportion of false flags among those raised (a more lenient middle ground). Rule of thumb: use the marginal p-value for a single pre-specified comparison, and a corrected p-value when screening the whole table – the usual workflow.

References

Ferreira, J. A. (2024). Methods of testing a 'small' or 'moderate' number of hypotheses simultaneously. Journal of Statistical Theory and Practice, 19(6). \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1007/s42519-024-00412-4")}

Westfall, P. H., & Young, S. S. (1993). Resampling-Based Multiple Testing. Wiley.

See Also

RMdimCFACutoff, RMdimCFAPlot

Examples


if (requireNamespace("lavaan", quietly = TRUE) &&
    requireNamespace("eRm", quietly = TRUE)) {
  data("raschdat1", package = "eRm")
  sim <- RMdimCFACutoff(raschdat1[, 1:8], iterations = 50,
                        parallel = FALSE, seed = 1)
  tabs <- RMdimCFA(raschdat1[, 1:8], cutoff = sim)
  tabs$fit
  tabs$loadings

  # Bootstrap p-values with family-wise (Westfall-Young) correction
  # (use iterations >= 1000 in real analyses for stable p-values)
  RMdimCFA(raschdat1[, 1:8], cutoff = sim, p_value = TRUE)
}



easyRasch2 documentation built on Sept. 13, 2026, 1:07 a.m.