From 546c2c6e570ca07dd8f77b86c59efdbbd18adb20 Mon Sep 17 00:00:00 2001 From: kss2k Date: Tue, 17 Mar 2026 08:56:27 +0100 Subject: [PATCH 1/4] Refactor code for `compositeRVCOV()` --- R/reliablity_single_item.R | 62 ++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 36 deletions(-) diff --git a/R/reliablity_single_item.R b/R/reliablity_single_item.R index d8b5e5f3..358de63c 100644 --- a/R/reliablity_single_item.R +++ b/R/reliablity_single_item.R @@ -598,47 +598,37 @@ calcAVE <- function(lambda.std, lV) { } -getCompositeDenominator <- function(lV, parTable, cfa, scale.corrected) { - measr <- parTable[parTable$lhs == lV & parTable$op == "=~", ] - inds <- unique(measr$rhs) - mats <- lavaan::lavInspect(cfa, what = "coef") - if (scale.corrected) { - sum(as.vector(mats$lambda[inds, lV])) - } else { - length(inds) # rowMeans: divide sum by k - } -} +getCompositeRVCOV <- function(lVs, parTable, cfa, scale.corrected) { + matrices <- lavaan::lavInspect(cfa, what = "coef") + lambda <- matrices$lambda + theta <- matrices$theta + inds <- rownames(lambda)[apply(lambda, MARGIN = 1L, FUN = \(x) any(x != 0))] + lambda <- lambda[inds, lVs, drop = FALSE] + theta <- theta[inds, inds, drop = FALSE] -getCompositeRVCOV <- function(lVs, parTable, cfa, scale.corrected) { - # Build Theta blocks and denominators - mats <- lavaan::lavInspect(cfa, what = "coef") - thetaF <- mats$theta + I <- lambda + I[I != 0] <- 1 - # item lists per LV - item_list <- lapply(lVs, function(lv) - unique(parTable[parTable$lhs == lv & parTable$op == "=~", "rhs"]) - ) - names(item_list) <- lVs + T <- t(I) %*% theta %*% I - # denominators D_f - denom <- vapply(lVs, function(lv) - getCompositeDenominator(lv, parTable, cfa, scale.corrected), - numeric(1) - ) + if (scale.corrected) { + l <- apply(lambda, MARGIN = 2L, FUN = sum) + + l.inv <- 1 / l + l.inv[l <= 0] <- 1L - p <- length(lVs) - resCov <- matrix(0, p, p, dimnames = list(lVs, lVs)) - - for (i in seq_len(p)) { - Ii <- item_list[[i]] - for (j in i:p) { - Ij <- item_list[[j]] - block_sum <- sum(thetaF[Ii, Ij, drop = FALSE]) - val <- block_sum / (denom[i] * denom[j]) - resCov[i, j] <- val - resCov[j, i] <- val + if (length(l.inv) > 1) { + L.inv <- diag(l.inv) + dimnames(L.inv) <- list(names(l.inv), names(l.inv)) + + } else { + L.inv <- matrix(l.inv, nrow = 1, ncol = 1) + dimnames(L.inv) <- list(names(l.inv), names(l.inv)) } + + T <- L.inv %*% T %*% L.inv } - resCov + + T } From 9f7125e0425f24b24740b8b57159eab2b053f5b3 Mon Sep 17 00:00:00 2001 From: kss2k Date: Tue, 17 Mar 2026 09:18:05 +0100 Subject: [PATCH 2/4] Fix codex comments --- R/reliablity_single_item.R | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/R/reliablity_single_item.R b/R/reliablity_single_item.R index 358de63c..757a1ace 100644 --- a/R/reliablity_single_item.R +++ b/R/reliablity_single_item.R @@ -607,28 +607,23 @@ getCompositeRVCOV <- function(lVs, parTable, cfa, scale.corrected) { lambda <- lambda[inds, lVs, drop = FALSE] theta <- theta[inds, inds, drop = FALSE] - I <- lambda - I[I != 0] <- 1 - + I <- sign(lambda) T <- t(I) %*% theta %*% I - if (scale.corrected) { - l <- apply(lambda, MARGIN = 2L, FUN = sum) + .f <- if (scale.corrected) sum else length - l.inv <- 1 / l - l.inv[l <= 0] <- 1L + l <- apply(lambda, MARGIN = 2L, FUN = .f) + l.inv <- 1 / l + l.inv[l <= 0] <- 1L - if (length(l.inv) > 1) { - L.inv <- diag(l.inv) - dimnames(L.inv) <- list(names(l.inv), names(l.inv)) + if (length(l.inv) > 1) { + L.inv <- diag(l.inv) + dimnames(L.inv) <- list(names(l.inv), names(l.inv)) - } else { - L.inv <- matrix(l.inv, nrow = 1, ncol = 1) - dimnames(L.inv) <- list(names(l.inv), names(l.inv)) - } - - T <- L.inv %*% T %*% L.inv + } else { + L.inv <- matrix(l.inv, nrow = 1, ncol = 1) + dimnames(L.inv) <- list(names(l.inv), names(l.inv)) } - T + L.inv %*% T %*% L.inv } From 19c0bf151390ee42e2ce6b8cc687e51dad33f606 Mon Sep 17 00:00:00 2001 From: kss2k Date: Tue, 17 Mar 2026 09:20:45 +0100 Subject: [PATCH 3/4] Don't use sign(I) --- R/reliablity_single_item.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/reliablity_single_item.R b/R/reliablity_single_item.R index 757a1ace..b6e09d78 100644 --- a/R/reliablity_single_item.R +++ b/R/reliablity_single_item.R @@ -607,7 +607,9 @@ getCompositeRVCOV <- function(lVs, parTable, cfa, scale.corrected) { lambda <- lambda[inds, lVs, drop = FALSE] theta <- theta[inds, inds, drop = FALSE] - I <- sign(lambda) + I <- lambda + I[I!=0] <- 1 + T <- t(I) %*% theta %*% I .f <- if (scale.corrected) sum else length From fbd7de117bd6a8ea32e9685b873c649481c49e8c Mon Sep 17 00:00:00 2001 From: kss2k Date: Tue, 17 Mar 2026 09:26:01 +0100 Subject: [PATCH 4/4] Check non-zero values, not length --- R/reliablity_single_item.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/reliablity_single_item.R b/R/reliablity_single_item.R index b6e09d78..0386d1fb 100644 --- a/R/reliablity_single_item.R +++ b/R/reliablity_single_item.R @@ -612,9 +612,9 @@ getCompositeRVCOV <- function(lVs, parTable, cfa, scale.corrected) { T <- t(I) %*% theta %*% I - .f <- if (scale.corrected) sum else length + FUN <- if (scale.corrected) sum else \(x) sum(x != 0) - l <- apply(lambda, MARGIN = 2L, FUN = .f) + l <- apply(lambda, MARGIN = 2L, FUN = FUN) l.inv <- 1 / l l.inv[l <= 0] <- 1L