Skip to content
51 changes: 43 additions & 8 deletions R/check_collinearity.R
Original file line number Diff line number Diff line change
Expand Up @@ -447,7 +447,7 @@
}


.check_collinearity <- function(x, component, ci = 0.95, verbose = TRUE) {

Check warning on line 450 in R/check_collinearity.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/check_collinearity.R,line=450,col=1,[cyclocomp_linter] Reduce the cyclomatic complexity of this expression from 48 to at most 40. Consider replacing high-complexity sections like loops and branches with helper functions.

Check warning on line 450 in R/check_collinearity.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/check_collinearity.R,line=450,col=1,[cyclocomp_linter] Reduce the cyclomatic complexity of this expression from 48 to at most 40. Consider replacing high-complexity sections like loops and branches with helper functions.
v <- .safe(insight::get_varcov(x, component = component, verbose = FALSE))

# sanity check
Expand Down Expand Up @@ -481,6 +481,49 @@
return(NULL)
}

# Filter to true slope parameters (handles multiple intercepts in ordinal models)
if (inherits(x, c("clm", "clmm"))) {
# names(x$beta) returns only non-singular (surviving) slopes
slope_names <- names(x$beta)
keep_idx <- which(colnames(v) %in% slope_names)
Comment thread
jmgirard marked this conversation as resolved.

# Rebuild term_assign by matching model matrix columns to surviving slopes
tryCatch(
{
mm <- insight::get_modelmatrix(x)
assign_attr <- attr(mm, "assign")
if (!is.null(assign_attr)) {
# Use name-matching to isolate indices for estimated slopes
match_idx <- which(colnames(mm) %in% slope_names)
if (length(match_idx) > 0) {
term_assign <- assign_attr[match_idx]
}
}
},
error = function(e) NULL
)
} else if (insight::has_intercept(x)) {
Comment thread
jmgirard marked this conversation as resolved.
# Standard behavior: drop the first column/row (the singular intercept)
keep_idx <- seq_len(ncol(v))[-1]
} else {
keep_idx <- seq_len(ncol(v))
if (isTRUE(verbose)) {
insight::format_alert("Model without intercept. VIFs may not be sensible.")
}
}

# Safely subset the matrix (term_assign is already synced for ordinal models)
if (length(keep_idx) < ncol(v)) {
if (
!inherits(x, c("clm", "clmm")) &&
!is.null(term_assign) &&
length(term_assign) == ncol(v)
) {
term_assign <- term_assign[keep_idx]
}
v <- v[keep_idx, keep_idx, drop = FALSE]
}

# we have rank-deficiency here. remove NA columns from assignment
if (isTRUE(attributes(v)$rank_deficient) && !is.null(attributes(v)$na_columns_index)) {
term_assign <- term_assign[-attributes(v)$na_columns_index]
Expand All @@ -491,14 +534,6 @@
}
}
Comment thread
jmgirard marked this conversation as resolved.

# check for missing intercept
if (insight::has_intercept(x)) {
v <- v[-1, -1]
term_assign <- term_assign[-1]
} else if (isTRUE(verbose)) {
insight::format_alert("Model has no intercept. VIFs may not be sensible.")
}

f <- insight::find_formula(x, verbose = FALSE)

# hurdle or zeroinfl model can have no zero-inflation formula, in which case
Expand Down Expand Up @@ -535,7 +570,7 @@
return(NULL)
}

R <- stats::cov2cor(v)

Check warning on line 573 in R/check_collinearity.R

View workflow job for this annotation

GitHub Actions / lint-changed-files / lint-changed-files

file=R/check_collinearity.R,line=573,col=3,[object_overwrite_linter] 'R' is an exported object from package 'tools'. Avoid re-using such symbols.

Check warning on line 573 in R/check_collinearity.R

View workflow job for this annotation

GitHub Actions / lint / lint

file=R/check_collinearity.R,line=573,col=3,[object_overwrite_linter] 'R' is an exported object from package 'tools'. Avoid re-using such symbols.
detR <- det(R)

result <- vector("numeric")
Expand Down
Loading