@@ -432,23 +432,44 @@ build_factor_correlation <- function(data, correlation_type = c("pearson", "poly
432432 type = " pearson" , smoothed = FALSE , warnings = character (), failed = FALSE ))
433433 }
434434
435+ # psych::polychoric / tetrachoric / mixedCor can fail on sparse contingency tables when the
436+ # continuity correction (default correct=0.5) produces empty pairwise results. psych itself
437+ # suggests retrying with correct=0; without that retry we used to degrade straight to Pearson
438+ # even though the polychoric-family estimate was recoverable (same root cause as the
439+ # Cronbach's Alpha fix).
435440 captured <- character ()
436- result <- withCallingHandlers(
437- tryCatch({
438- switch (correlation_type ,
439- polychoric = psych :: polychoric(data , correct = correct ),
440- tetrachoric = psych :: tetrachoric(data , correct = correct ),
441- mixed = psych :: mixedCor(data ))
442- }, error = function (e ) {
443- captured <<- c(captured , conditionMessage(e ))
444- NULL
445- }),
446- warning = function (w ) {
447- captured <<- c(captured , conditionMessage(w ))
448- invokeRestart(" muffleWarning" )
449- })
450-
451- if (is.null(result ) || is.null(result $ rho ) || anyNA(result $ rho )) {
441+ run_psych_correlation <- function (corr ) {
442+ withCallingHandlers(
443+ tryCatch({
444+ switch (correlation_type ,
445+ polychoric = psych :: polychoric(data , correct = corr ),
446+ tetrachoric = psych :: tetrachoric(data , correct = corr ),
447+ mixed = psych :: mixedCor(data , correct = corr ))
448+ }, error = function (e ) {
449+ captured <<- c(captured , conditionMessage(e ))
450+ NULL
451+ }),
452+ warning = function (w ) {
453+ captured <<- c(captured , conditionMessage(w ))
454+ invokeRestart(" muffleWarning" )
455+ })
456+ }
457+ correlation_ok <- function (obj ) {
458+ ! is.null(obj ) && ! is.null(obj $ rho ) && ! anyNA(obj $ rho )
459+ }
460+
461+ result <- run_psych_correlation(correct )
462+ if (! correlation_ok(result ) && correct != 0 ) {
463+ result <- run_psych_correlation(0 )
464+ if (correlation_ok(result )) {
465+ captured <- c(
466+ captured ,
467+ sprintf(" %s used continuity correction of 0 because the default correction failed." ,
468+ factanal_correlation_label(correlation_type )))
469+ }
470+ }
471+
472+ if (! correlation_ok(result )) {
452473 # Degrade to Pearson rather than aborting the whole analysis. A partially-NA matrix counts as a
453474 # failure too: psych::fa() refuses to run on one ("missing values (NAs) in the correlation
454475 # matrix do not allow me to continue"), so keeping it would abort with a raw psych error.
0 commit comments