NEWS


OptimalFactor 1.5.0 (2026-10-24)

Resubmission after CRAN review (2026-10-15)

Preparation for CRAN

Choosing between algorithms: how much theory survives, and does the choice replicate

The package offers several purification routines, and on a given scale they disagree. Two functions put them on the same footing so the choice can be argued rather than asserted.

Bug fix

OptimalFactor 1.4.0

Two routines for scales that fit but do not measure what they claim

A model can fit well and still be uninterpretable. Four factors correlating .97 reproduce the covariance matrix as well as one factor does, so CFI and RMSEA say nothing about whether the factors exist. These two functions target what the fit indices miss.

Reliability and loading floors are now adaptive

Both routines treat omega_min and min_loading as adaptive: a model already below a floor is not frozen, its effective bar becomes its current value. A floor set above the starting value rejects every candidate and stalls the search on the first iteration --- a failure mode indistinguishable, from the outside, from a genuine negative result.

Documentation

OptimalFactor 1.3.0

Breaking-free change: no more PsyMetricTools dependency

New functions

cfa_boosting() enforces its own loading floor

The confirmatory simulation was built to evaluate the pipeline and immediately found a defect in it. The optimisation loop tested the fit targets first and broke as soon as they were met, so the low-loading check further down was unreachable: an item the user's own thresholds$loading declares inadmissible survived untouched whenever global fit happened to be acceptable. And global fit is acceptable far more often than one would hope. In simulation, a population item loading .20 sat inside a model with RMSEA = .03, and adding cross-loading items barely moved the index at all: with six items cross-loading at .60, RMSEA stayed at .053 while CFI rose to .997, because omitted cross-loadings are absorbed by the interfactor correlation instead of degrading fit.

Misspecified dimensionality: n_factors_fitted

Every condition in a recovery design hands the pipeline the true number of factors, and in practice nobody knows it. simulate_recovery() gains n_factors_fitted, crossed like the other conditions, so the population keeps its own dimensionality while the algorithm is told something else.

The answer is asymmetric, and the asymmetry is the practical finding. Against a three-factor population with 12 good items, one cross-loading item and one weak one (12 replications):

| fitted | recovery | sensitivity | specificity | retained | |-------:|---------:|------------:|------------:|---------:| | 2 | .000 | .750 / .542 | .729 / .653 | 9.25 / 8.75 | | 3 | 1.000 | .875 | 1.000 | 12.25 | | 4 | .667 / .556 | .000 | .986 / 1.000 | 13.83 / 14.00 |

Extracting too few factors is destructive: specificity collapses to .65-.73, so between three and four good items are discarded to force the data into a structure that cannot hold them. Extracting too many makes the pipeline inert instead: sensitivity falls to zero, no contaminated item is removed at all, and 18 of 24 replications stop at min_items_per_factor_protected, because with four factors and fourteen items almost any removal breaches the minimum. The scale survives untouched, which is the harmless failure.

The practical reading: when the dimensionality is uncertain, erring towards more factors leaves the algorithm conservative, while erring towards fewer leaves it removing good items.

Population model: cross-loading items no longer share a factor pair

simulate_recovery() and simulate_cfa_recovery() used to place every cross-loading item on the same two factors. With more than one such item that makes them clones: they correlate strongly, form a coherent cluster, and the rotation reports the cluster as a factor of its own, each item showing a single clean loading near .80. No item-level criterion can call that a cross-loading, because in the estimated solution it no longer is one, and the good items get displaced to make room for it. They are now spread over different pairs.

The correction matters because it inverts the verdict. Under three cross-loading items at .55 plus two weak ones, the old generator made efa_boosting() look defective (sensitivity .617/.700, recovery falling to .75 at N = 600, contaminated items left in the pool). With the population correctly specified the same conditions give sensitivity .983/1.000, recovery 1.000 and specificity 1.000, retaining 12.08 and 12.00 items against the 12 good ones in the population. The apparent defect was the measuring instrument.

Progress, timeouts and parallel robustness

Resampling exposed three things that made these functions unusable in practice rather than merely slow.

Performance

Bug fixes

Tests

Reliability floor

OptimalFactor 1.2.2

CRAN readiness

OptimalFactor 1.2.1

OptimalFactor 1.2.0

Breaking changes

New functions

Deprecated

OptimalFactor 1.1.0

New: Guided wizard for EFA-Boosting

Wizard features

Improvements to efa_boosting()

New helpers

OptimalFactor 1.0.0

Initial CRAN Release

Main Features

Data

Dependencies

References