Real-world item sets often contain columns that break or silently degrade
a factor analysis. A factor is a summary variable standing in for a group of
items that move together. Three columns cause most of the trouble. One is an
item everyone answered the same way (no variance). Another is an item
dominated by one response with a couple of stray answers. The third is an
item with heavy missingness. These are especially costly on the polychoric
basis, which estimates the correlation between the continuous traits
assumed to underlie ordered responses. A near-empty response category can
make
psych::polychoric() fail outright (see the correct argument of
ackwards()). A near-constant item can produce a plausible-looking but
meaningless factor with no warning.
check_items() reports these problems before you fit, one row per item, so
you can collapse rare categories, drop degenerate items, or set
cor and correct deliberately rather than debugging a cryptic error. It
only reports, and never changes your data. ackwards() runs the same screen
internally. It errors on a constant item and warns on a
near-degenerate one, naming the offenders.
Usage
check_items(data, cor = c("polychoric", "pearson", "spearman"))Value
A data frame (class check_items) with one row per item and columns
item, n_valid, pct_missing, n_distinct, min_count (smallest
observed category count), top_prop (proportion of valid responses in the
most common value). The last column, flag, is one of "ok",
"constant", "near-constant", "sparse category", or "high missing".
Print it for a grouped summary with guidance. Treat it as a plain data
frame for the full per-item table.
See also
ackwards() and its correct argument (the polychoric failure
this screens for). Also factorability(), suggest_k(), and
comparability(), the other pre-analysis diagnostics.
Examples
# sim16 is clean continuous data -> nothing flagged
check_items(sim16, cor = "pearson")
#>
#> ── Item quality check (ackwards) ───────────────────────────────────────────────
#> Basis: pearson
#> Items: 16
#> Flagged: 0
#> ✔ No item problems detected.
#> ────────────────────────────────────────────────────────────────────────────────
#> Constant items must be dropped (no variance). A near-constant item (one
#> response dominates) can yield a meaningless factor; a sparse category can make
#> `cor = "polychoric"` fail -- collapse rare categories, try `correct = 0`, or
#> drop the item. Full per-item table: treat this object as a data frame.
# An item dominated by one response with a couple of stray answers is flagged
d <- sim16
d$bad <- c(rep(1L, nrow(d) - 2L), 2L, 3L)
check_items(d)
#>
#> ── Item quality check (ackwards) ───────────────────────────────────────────────
#> Basis: polychoric
#> Items: 17
#> Flagged: 17
#>
#> ── Flagged items ──
#>
#> ! near-constant: "bad"
#> ! sparse category: "i1", "i2", "i3", "i4", "i5", "i6", "i7", "i8", "i9", "i10",
#> "i11", "i12", "i13", "i14", "i15", and "i16"
#> ────────────────────────────────────────────────────────────────────────────────
#> Constant items must be dropped (no variance). A near-constant item (one
#> response dominates) can yield a meaningless factor; a sparse category can make
#> `cor = "polychoric"` fail -- collapse rare categories, try `correct = 0`, or
#> drop the item. Full per-item table: treat this object as a data frame.
