prune: Flag redundant or artifactual factors (Forbes 2023 extension)

View source: R/prune.R

pruneR Documentation

Flag redundant or artifactual factors (Forbes 2023 extension)

Description

prune() never removes anything from an ackwards object – it only annotates factors with pruned/prune_reason flags in x$prune$nodes (flag-only, never removes; the object keeps every level). Because it is a separate, cheap step from extraction, you can re-prune with new thresholds without re-running ackwards():

  x <- ackwards(bfi25, k_max = 6, engine = "esem")  # expensive
  x |> prune("redundant")                            # cheap, repeatable
  x |> prune("redundant", redundancy_r = 0.95)        # no re-extraction

prune() is an S3 generic (rather than a plain function) so it coexists with the prune generics already defined by recursive-partitioning packages (e.g. rpart::prune) regardless of package load order.

Usage

prune(x, ...)

## S3 method for class 'ackwards'
prune(
  x,
  rules = "none",
  manual = NULL,
  redundancy_r = 0.9,
  redundancy_phi = NULL,
  redundancy_criterion = c("direct", "adjacent"),
  min_items = 3L,
  orphan_r = 0.5,
  ...
)

Arguments

x

An ackwards object.

...

Reserved for future methods/arguments.

rules

Character vector controlling which auto-rules run. Default "none" (no auto rule; combine with manual for pure manual pruning, or call prune(x) with no arguments to clear any existing pruning). Options:

  • "redundant" – identify chains of factors connected by score correlations ⁠|r| >= redundancy_r⁠ (and optionally phi > redundancy_phi), using redundancy_criterion (default "direct", faithful to Forbes). Applies Forbes's (2023) retention rule: keep the bottom node when the chain reaches level k_max (most specific); keep the top node otherwise. Flagged nodes get pruned = TRUE and prune_reason = "redundant" in x$prune$nodes.

  • "artifact" (or the alias "artefact", normalized to "artifact") – compute Tucker's congruence coefficient (phi) for all cross-level factor pairs and store in x$prune$phi, plus structural signals (few_items/orphan/split_merge) in x$prune$structural. No factors are auto-flagged; artifact identification requires judgment (Forbes, 2023; Wicherts et al., 2016).

manual

Character vector of factor labels (e.g. c("m4f3", "m4f4")) to flag directly, in addition to or instead of an auto rule. Standalone manual pruning is supported: prune(x, manual = c("m4f3")). Unknown labels error. A node already flagged by an auto rule keeps that prune_reason; only otherwise-unflagged manual nodes get prune_reason = "manual".

redundancy_r

Scalar in ⁠(0, 1]⁠. Score-correlation ⁠|r|⁠ threshold for redundancy chains. Default 0.9 (Forbes, 2023).

redundancy_phi

Scalar in ⁠(0, 1]⁠, NULL (default, auto), or NA (explicit opt-out). When NULL:

  • x$engine == "pca" – no phi filter. Component scores are determinate (exact linear functions of the data, with no factor-score indeterminacy), so the score correlation ⁠|r|⁠ is the true correlation between the components themselves; phi adds nothing that ⁠|r|⁠ does not already capture.

  • x$engine is "efa" or "esem" – automatically set to 0.95 (Lorenzo-Seva & ten Berge, 2006). Factor-score indeterminacy off-PCA means ⁠|r|⁠-alone is liberal; the conjunctive phi criterion is the conservative default. A cli message announces the resolved value. Pass NA to disable phi filtering regardless of engine. Pass a numeric value to override on any engine.

redundancy_criterion

How redundancy chains are traced. One of:

  • "direct" (default) – chase upward via the direct (skip-level) correlation between a factor and each ancestor level, continuing while ⁠|r| >= redundancy_r⁠ contiguously. This is Forbes's (2023) published ChaseCorrPaths rule and the honest operationalization of "the same construct" (two factor scores share ⁠>= redundancy_r^2⁠ variance directly). It reproduces her AMH applied example exactly.

  • "adjacent" – trace adjacent primary-parent links only (each consecutive level ⁠|r| >= redundancy_r⁠). This was the pre-M53 default; because correlation is non-transitive it can both over- and under-flag versus "direct" in deep (many-level) hierarchies, so it is retained only as an opt-in. On shallow/transitive hierarchies the two agree.

min_items

Minimum number of items for which a factor must be the primary loader (highest ⁠|loading|⁠). Factors with fewer than min_items primary items are flagged few_items = TRUE in x$prune$structural. Only used when rules includes "artifact". Default 3L – a factor defined by one or two items is under-identified and frequently an extraction artifact rather than a replicable construct (the classic "three-indicator rule"; Forbes, 2023, Fig. 2).

orphan_r

Threshold for the orphan structural signal. A factor whose maximum adjacent-level ⁠|r|⁠ (to the immediately shallower and deeper levels) falls below orphan_r is flagged orphan = TRUE in x$prune$structural – it does not connect to the neighbouring solutions and so does not replicate across the hierarchy. Only used when rules includes "artifact". Default 0.5 – a moderate correlation; a factor that shares less than a quarter of its variance with every neighbour is a structural outlier worth inspecting.

Details

Reading x$prune$chains under redundancy_criterion = "direct". The r_to_prev and phi_to_prev columns report the adjacent-level correlation and congruence between consecutive chain members (for continuity of display), but chain membership is decided by the direct (skip-level) correlation to the chain's deepest factor. A direct chain can therefore legitimately contain a link whose r_to_prev is below redundancy_r – the stronger direct link is what justified it. The endpoint_r column gives the direct root-to-leaf correlation as an at-a-glance cross-check. Under redundancy_criterion = "adjacent", r_to_prev is the criterion and always meets redundancy_r.

Value

x, with ⁠$prune⁠ populated (replacing any prior pruning).

References

Forbes, M. K. (2023). Improving hierarchical models of individual differences: An extension of Goldberg's bass-ackward method. Psychological Methods. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1037/met0000546")}

Lorenzo-Seva, U., & ten Berge, J. M. F. (2006). Tucker's congruence coefficient as a meaningful index of factor similarity. Methodology, 2(2), 57–64. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1027/1614-2241.2.2.57")}

See Also

ackwards(), tidy.ackwards() (what = "nodes"), autoplot.ackwards() (drop_pruned)

Examples

# sim16 has a planted redundant chain + overextraction artifact at k = 5,
# so the prune rules always have a finding to show (and no ordinal warning).
x <- ackwards(sim16, k_max = 5)

xp <- prune(x, "redundant")
xp$prune$nodes

# Re-prune with a new threshold -- no re-extraction needed
prune(x, "redundant", redundancy_r = 0.95)

# Manual pruning: standalone, or mixed with an auto rule
prune(x, manual = "m4f2")
prune(x, "redundant", manual = "m4f2")


ackwards documentation built on July 25, 2026, 1:08 a.m.