From 734187721299428546ea2b0e124f86e523b91865 Mon Sep 17 00:00:00 2001 From: Sebastian Jentschke Date: Tue, 9 Sep 2025 08:43:42 +1000 Subject: [PATCH 1/5] Added UI elements for data summary in EFA and PCA --- R/efa.h.R | 76 +++++++++++++++++++++++++++++-------------- R/pca.h.R | 82 +++++++++++++++++++++++++++++++---------------- jamovi/efa.a.yaml | 56 ++++++++++++++++++++++---------- jamovi/efa.u.yaml | 9 ++++++ jamovi/pca.a.yaml | 56 ++++++++++++++++++++++---------- jamovi/pca.u.yaml | 9 ++++++ 6 files changed, 203 insertions(+), 85 deletions(-) diff --git a/R/efa.h.R b/R/efa.h.R index 030cbb58..83b887b7 100644 --- a/R/efa.h.R +++ b/R/efa.h.R @@ -12,6 +12,10 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = 0, extraction = "minres", rotation = "oblimin", + minCorrThr = 0.3, + maxCorrThr = 0.9, + kmo = FALSE, + bartlett = FALSE, hideLoadings = 0.3, sortLoadings = FALSE, screePlot = FALSE, @@ -19,8 +23,6 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( factorCor = FALSE, factorSummary = FALSE, modelFit = FALSE, - kmo = FALSE, - bartlett = FALSE, factorScoreMethod = "Thurstone", ...) { super$initialize( @@ -75,6 +77,26 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="oblimin") + private$..minCorrThr <- jmvcore::OptionNumber$new( + "minCorrThr", + minCorrThr, + min=0, + max=1, + default=0.3) + private$..maxCorrThr <- jmvcore::OptionNumber$new( + "maxCorrThr", + maxCorrThr, + min=0, + max=1, + default=0.9) + private$..kmo <- jmvcore::OptionBool$new( + "kmo", + kmo, + default=FALSE) + private$..bartlett <- jmvcore::OptionBool$new( + "bartlett", + bartlett, + default=FALSE) private$..hideLoadings <- jmvcore::OptionNumber$new( "hideLoadings", hideLoadings, @@ -103,14 +125,6 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "modelFit", modelFit, default=FALSE) - private$..kmo <- jmvcore::OptionBool$new( - "kmo", - kmo, - default=FALSE) - private$..bartlett <- jmvcore::OptionBool$new( - "bartlett", - bartlett, - default=FALSE) private$..factorScoresOV <- jmvcore::OptionOutput$new( "factorScoresOV") private$..factorScoreMethod <- jmvcore::OptionList$new( @@ -130,6 +144,10 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..minEigen) self$.addOption(private$..extraction) self$.addOption(private$..rotation) + self$.addOption(private$..minCorrThr) + self$.addOption(private$..maxCorrThr) + self$.addOption(private$..kmo) + self$.addOption(private$..bartlett) self$.addOption(private$..hideLoadings) self$.addOption(private$..sortLoadings) self$.addOption(private$..screePlot) @@ -137,8 +155,6 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..factorCor) self$.addOption(private$..factorSummary) self$.addOption(private$..modelFit) - self$.addOption(private$..kmo) - self$.addOption(private$..bartlett) self$.addOption(private$..factorScoresOV) self$.addOption(private$..factorScoreMethod) }), @@ -149,6 +165,10 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = function() private$..minEigen$value, extraction = function() private$..extraction$value, rotation = function() private$..rotation$value, + minCorrThr = function() private$..minCorrThr$value, + maxCorrThr = function() private$..maxCorrThr$value, + kmo = function() private$..kmo$value, + bartlett = function() private$..bartlett$value, hideLoadings = function() private$..hideLoadings$value, sortLoadings = function() private$..sortLoadings$value, screePlot = function() private$..screePlot$value, @@ -156,8 +176,6 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( factorCor = function() private$..factorCor$value, factorSummary = function() private$..factorSummary$value, modelFit = function() private$..modelFit$value, - kmo = function() private$..kmo$value, - bartlett = function() private$..bartlett$value, factorScoresOV = function() private$..factorScoresOV$value, factorScoreMethod = function() private$..factorScoreMethod$value), private = list( @@ -167,6 +185,10 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..minEigen = NA, ..extraction = NA, ..rotation = NA, + ..minCorrThr = NA, + ..maxCorrThr = NA, + ..kmo = NA, + ..bartlett = NA, ..hideLoadings = NA, ..sortLoadings = NA, ..screePlot = NA, @@ -174,8 +196,6 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..factorCor = NA, ..factorSummary = NA, ..modelFit = NA, - ..kmo = NA, - ..bartlett = NA, ..factorScoresOV = NA, ..factorScoreMethod = NA) ) @@ -263,6 +283,14 @@ efaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'}, \code{'quartimax'}, #' \code{'promax'}, \code{'oblimin'} (default), or \code{'simplimax'}, the #' rotation to use in estimation +#' @param minCorrThr a number (default: 0.3), count correlations between +#' variables that are above this threshold +#' @param maxCorrThr a number (default: 0.9), count correlations between +#' variables that are above this threshold +#' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin +#' (KMO) measure of sampling adequacy (MSA) results +#' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test +#' of sphericity results #' @param hideLoadings a number (default: 0.3), hide factor loadings below #' this value #' @param sortLoadings \code{TRUE} or \code{FALSE} (default), sort the factor @@ -275,10 +303,6 @@ efaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' summary #' @param modelFit \code{TRUE} or \code{FALSE} (default), show model fit #' measures and test -#' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin -#' (KMO) measure of sampling adequacy (MSA) results -#' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test -#' of sphericity results #' @param factorScoreMethod \code{'Thurstone'} (default), \code{'Bartlett'}, #' \code{'tenBerge'}, \code{'Anderson'}, or \code{'Harman'} use respectively #' 'Thurstone', 'Bartlett', 'ten Berge', 'Anderson & Rubin', or 'Harman' @@ -297,6 +321,10 @@ efa <- function( minEigen = 0, extraction = "minres", rotation = "oblimin", + minCorrThr = 0.3, + maxCorrThr = 0.9, + kmo = FALSE, + bartlett = FALSE, hideLoadings = 0.3, sortLoadings = FALSE, screePlot = FALSE, @@ -304,8 +332,6 @@ efa <- function( factorCor = FALSE, factorSummary = FALSE, modelFit = FALSE, - kmo = FALSE, - bartlett = FALSE, factorScoreMethod = "Thurstone") { if ( ! requireNamespace("jmvcore", quietly=TRUE)) @@ -326,6 +352,10 @@ efa <- function( minEigen = minEigen, extraction = extraction, rotation = rotation, + minCorrThr = minCorrThr, + maxCorrThr = maxCorrThr, + kmo = kmo, + bartlett = bartlett, hideLoadings = hideLoadings, sortLoadings = sortLoadings, screePlot = screePlot, @@ -333,8 +363,6 @@ efa <- function( factorCor = factorCor, factorSummary = factorSummary, modelFit = modelFit, - kmo = kmo, - bartlett = bartlett, factorScoreMethod = factorScoreMethod) analysis <- efaClass$new( diff --git a/R/pca.h.R b/R/pca.h.R index 3ad569d4..12dbad57 100644 --- a/R/pca.h.R +++ b/R/pca.h.R @@ -11,14 +11,16 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( nFactors = 1, minEigen = 1, rotation = "varimax", + minCorrThr = 0.3, + maxCorrThr = 0.9, + kmo = FALSE, + bartlett = FALSE, hideLoadings = 0.3, sortLoadings = FALSE, screePlot = FALSE, eigen = FALSE, factorCor = FALSE, - factorSummary = FALSE, - kmo = FALSE, - bartlett = FALSE, ...) { + factorSummary = FALSE, ...) { super$initialize( package="jmv", @@ -64,6 +66,26 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="varimax") + private$..minCorrThr <- jmvcore::OptionNumber$new( + "minCorrThr", + minCorrThr, + min=0, + max=1, + default=0.3) + private$..maxCorrThr <- jmvcore::OptionNumber$new( + "maxCorrThr", + maxCorrThr, + min=0, + max=1, + default=0.9) + private$..kmo <- jmvcore::OptionBool$new( + "kmo", + kmo, + default=FALSE) + private$..bartlett <- jmvcore::OptionBool$new( + "bartlett", + bartlett, + default=FALSE) private$..hideLoadings <- jmvcore::OptionNumber$new( "hideLoadings", hideLoadings, @@ -88,14 +110,6 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "factorSummary", factorSummary, default=FALSE) - private$..kmo <- jmvcore::OptionBool$new( - "kmo", - kmo, - default=FALSE) - private$..bartlett <- jmvcore::OptionBool$new( - "bartlett", - bartlett, - default=FALSE) private$..factorScoresOV <- jmvcore::OptionOutput$new( "factorScoresOV") @@ -104,14 +118,16 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..nFactors) self$.addOption(private$..minEigen) self$.addOption(private$..rotation) + self$.addOption(private$..minCorrThr) + self$.addOption(private$..maxCorrThr) + self$.addOption(private$..kmo) + self$.addOption(private$..bartlett) self$.addOption(private$..hideLoadings) self$.addOption(private$..sortLoadings) self$.addOption(private$..screePlot) self$.addOption(private$..eigen) self$.addOption(private$..factorCor) self$.addOption(private$..factorSummary) - self$.addOption(private$..kmo) - self$.addOption(private$..bartlett) self$.addOption(private$..factorScoresOV) }), active = list( @@ -120,14 +136,16 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( nFactors = function() private$..nFactors$value, minEigen = function() private$..minEigen$value, rotation = function() private$..rotation$value, + minCorrThr = function() private$..minCorrThr$value, + maxCorrThr = function() private$..maxCorrThr$value, + kmo = function() private$..kmo$value, + bartlett = function() private$..bartlett$value, hideLoadings = function() private$..hideLoadings$value, sortLoadings = function() private$..sortLoadings$value, screePlot = function() private$..screePlot$value, eigen = function() private$..eigen$value, factorCor = function() private$..factorCor$value, factorSummary = function() private$..factorSummary$value, - kmo = function() private$..kmo$value, - bartlett = function() private$..bartlett$value, factorScoresOV = function() private$..factorScoresOV$value), private = list( ..vars = NA, @@ -135,14 +153,16 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..nFactors = NA, ..minEigen = NA, ..rotation = NA, + ..minCorrThr = NA, + ..maxCorrThr = NA, + ..kmo = NA, + ..bartlett = NA, ..hideLoadings = NA, ..sortLoadings = NA, ..screePlot = NA, ..eigen = NA, ..factorCor = NA, ..factorSummary = NA, - ..kmo = NA, - ..bartlett = NA, ..factorScoresOV = NA) ) @@ -480,6 +500,14 @@ pcaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'} (default), #' \code{'quartimax'}, \code{'promax'}, \code{'oblimin'}, or #' \code{'simplimax'}, the rotation to use in estimation +#' @param minCorrThr a number (default: 0.3), count correlations between +#' variables that are above this threshold +#' @param maxCorrThr a number (default: 0.9), count correlations between +#' variables that are above this threshold +#' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin +#' (KMO) measure of sampling adequacy (MSA) results +#' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test +#' of sphericity results #' @param hideLoadings a number (default: 0.3), hide loadings below this value #' @param sortLoadings \code{TRUE} or \code{FALSE} (default), sort the factor #' loadings by size @@ -489,10 +517,6 @@ pcaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' correlations #' @param factorSummary \code{TRUE} or \code{FALSE} (default), show factor #' summary -#' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin -#' (KMO) measure of sampling adequacy (MSA) results -#' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test -#' of sphericity results #' @return A results object containing: #' \tabular{llllll}{ #' \code{results$loadings} \tab \tab \tab \tab \tab a table \cr @@ -520,14 +544,16 @@ pca <- function( nFactors = 1, minEigen = 1, rotation = "varimax", + minCorrThr = 0.3, + maxCorrThr = 0.9, + kmo = FALSE, + bartlett = FALSE, hideLoadings = 0.3, sortLoadings = FALSE, screePlot = FALSE, eigen = FALSE, factorCor = FALSE, - factorSummary = FALSE, - kmo = FALSE, - bartlett = FALSE) { + factorSummary = FALSE) { if ( ! requireNamespace("jmvcore", quietly=TRUE)) stop("pca requires jmvcore to be installed (restart may be required)") @@ -546,14 +572,16 @@ pca <- function( nFactors = nFactors, minEigen = minEigen, rotation = rotation, + minCorrThr = minCorrThr, + maxCorrThr = maxCorrThr, + kmo = kmo, + bartlett = bartlett, hideLoadings = hideLoadings, sortLoadings = sortLoadings, screePlot = screePlot, eigen = eigen, factorCor = factorCor, - factorSummary = factorSummary, - kmo = kmo, - bartlett = bartlett) + factorSummary = factorSummary) analysis <- pcaClass$new( options = options, diff --git a/jamovi/efa.a.yaml b/jamovi/efa.a.yaml index 3fc74cd5..1b38f55b 100644 --- a/jamovi/efa.a.yaml +++ b/jamovi/efa.a.yaml @@ -121,6 +121,45 @@ options: `'oblimin'` (default), or `'simplimax'`, the rotation to use in estimation + - name: minCorrThr + title: '' + type: Number + min: 0 + max: 1 + default: 0.3 + description: + R: > + a number (default: 0.3), count correlations between variables that + are above this threshold + + - name: maxCorrThr + title: '' + type: Number + min: 0 + max: 1 + default: 0.9 + description: + R: > + a number (default: 0.9), count correlations between variables that + are above this threshold + + - name: kmo + title: KMO measure of sampling adequacy + type: Bool + default: false + description: + R: > + `TRUE` or `FALSE` (default), show Kaiser-Meyer-Olkin (KMO) measure of + sampling adequacy (MSA) results + + - name: bartlett + title: Bartlett's test of sphericity + type: Bool + default: false + description: + R: > + `TRUE` or `FALSE` (default), show Bartlett's test of sphericity results + - name: hideLoadings title: Hide loadings below type: Number @@ -177,23 +216,6 @@ options: R: > `TRUE` or `FALSE` (default), show model fit measures and test - - name: kmo - title: KMO measure of sampling adequacy - type: Bool - default: false - description: - R: > - `TRUE` or `FALSE` (default), show Kaiser-Meyer-Olkin (KMO) measure of - sampling adequacy (MSA) results - - - name: bartlett - title: Bartlett's test of sphericity - type: Bool - default: false - description: - R: > - `TRUE` or `FALSE` (default), show Bartlett's test of sphericity results - - name: factorScoresOV title: Factor scores type: Output diff --git a/jamovi/efa.u.yaml b/jamovi/efa.u.yaml index 5d570680..313ab563 100644 --- a/jamovi/efa.u.yaml +++ b/jamovi/efa.u.yaml @@ -64,6 +64,15 @@ children: suffix: factor(s) format: number enable: (nFactorMethod_fixed) + - type: Label + label: Data Summary + children: + - name: minCorrThr + type: TextBox + format: number + - name: maxCorrThr + type: TextBox + format: number - type: LayoutBox margin: large cell: diff --git a/jamovi/pca.a.yaml b/jamovi/pca.a.yaml index af81ec76..9b535272 100644 --- a/jamovi/pca.a.yaml +++ b/jamovi/pca.a.yaml @@ -101,6 +101,45 @@ options: `'oblimin'`, or `'simplimax'`, the rotation to use in estimation + - name: minCorrThr + title: '' + type: Number + min: 0 + max: 1 + default: 0.3 + description: + R: > + a number (default: 0.3), count correlations between variables that + are above this threshold + + - name: maxCorrThr + title: '' + type: Number + min: 0 + max: 1 + default: 0.9 + description: + R: > + a number (default: 0.9), count correlations between variables that + are above this threshold + + - name: kmo + title: KMO measure of sampling adequacy + type: Bool + default: false + description: + R: > + `TRUE` or `FALSE` (default), show Kaiser-Meyer-Olkin (KMO) measure of + sampling adequacy (MSA) results + + - name: bartlett + title: Bartlett's test of sphericity + type: Bool + default: false + description: + R: > + `TRUE` or `FALSE` (default), show Bartlett's test of sphericity results + - name: hideLoadings title: Hide loadings below type: Number @@ -149,23 +188,6 @@ options: R: > `TRUE` or `FALSE` (default), show factor summary - - name: kmo - title: KMO measure of sampling adequacy - type: Bool - default: false - description: - R: > - `TRUE` or `FALSE` (default), show Kaiser-Meyer-Olkin (KMO) measure of - sampling adequacy (MSA) results - - - name: bartlett - title: Bartlett's test of sphericity - type: Bool - default: false - description: - R: > - `TRUE` or `FALSE` (default), show Bartlett's test of sphericity results - - name: factorScoresOV title: Component scores type: Output diff --git a/jamovi/pca.u.yaml b/jamovi/pca.u.yaml index 4584a816..41b68bfb 100644 --- a/jamovi/pca.u.yaml +++ b/jamovi/pca.u.yaml @@ -65,6 +65,15 @@ children: suffix: component(s) format: number enable: (nFactorMethod_fixed) + - type: Label + label: Data Summary + children: + - name: minCorrThr + type: TextBox + format: number + - name: maxCorrThr + type: TextBox + format: number - type: LayoutBox margin: large cell: From c6053f06e0356ad673d1dea4729bf26564d1e807 Mon Sep 17 00:00:00 2001 From: Sebastian Jentschke Date: Tue, 9 Sep 2025 12:05:27 +1000 Subject: [PATCH 2/5] Adjusted UI elements for data summary in EFA and PCA --- R/efa.h.R | 20 ++++++++++---------- R/pca.b.R | 2 ++ R/pca.h.R | 41 +++++++++++++++++++++++++++++++++++++++++ jamovi/efa.a.yaml | 12 ++++++------ jamovi/efa.u.yaml | 1 + jamovi/pca.r.yaml | 27 +++++++++++++++++++++++++++ jamovi/pca.u.yaml | 1 + 7 files changed, 88 insertions(+), 16 deletions(-) diff --git a/R/efa.h.R b/R/efa.h.R index 83b887b7..b0e15820 100644 --- a/R/efa.h.R +++ b/R/efa.h.R @@ -12,8 +12,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = 0, extraction = "minres", rotation = "oblimin", - minCorrThr = 0.3, - maxCorrThr = 0.9, + minCorrThr = 0, + maxCorrThr = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -82,13 +82,13 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minCorrThr, min=0, max=1, - default=0.3) + default=0) private$..maxCorrThr <- jmvcore::OptionNumber$new( "maxCorrThr", maxCorrThr, min=0, max=1, - default=0.9) + default=0) private$..kmo <- jmvcore::OptionBool$new( "kmo", kmo, @@ -283,10 +283,10 @@ efaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'}, \code{'quartimax'}, #' \code{'promax'}, \code{'oblimin'} (default), or \code{'simplimax'}, the #' rotation to use in estimation -#' @param minCorrThr a number (default: 0.3), count correlations between -#' variables that are above this threshold -#' @param maxCorrThr a number (default: 0.9), count correlations between -#' variables that are above this threshold +#' @param minCorrThr a number (default: 0), count correlations between +#' variables that are above this threshold (if 0, no output is produced) +#' @param maxCorrThr a number (default: 0), count correlations between +#' variables that are above this threshold (if 0, no output is produced) #' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin #' (KMO) measure of sampling adequacy (MSA) results #' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test @@ -321,8 +321,8 @@ efa <- function( minEigen = 0, extraction = "minres", rotation = "oblimin", - minCorrThr = 0.3, - maxCorrThr = 0.9, + minCorrThr = 0, + maxCorrThr = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, diff --git a/R/pca.b.R b/R/pca.b.R index 4dd47850..e423b4a8 100644 --- a/R/pca.b.R +++ b/R/pca.b.R @@ -116,6 +116,8 @@ pcaClass <- R6::R6Class( .run = function() { if (is.null(self$options$vars) || length(self$options$vars) < 2) return() +print(self$options$minCorrThr) +print(self$options$maxCorrThr) private$.errorCheck() diff --git a/R/pca.h.R b/R/pca.h.R index 12dbad57..3c062f8c 100644 --- a/R/pca.h.R +++ b/R/pca.h.R @@ -173,6 +173,7 @@ pcaResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( loadings = function() private$.items[["loadings"]], factorStats = function() private$.items[["factorStats"]], modelFit = function() private$.items[["modelFit"]], + dataSummary = function() private$.items[["dataSummary"]], assump = function() private$.items[["assump"]], eigen = function() private$.items[["eigen"]], factorScoresOV = function() private$.items[["factorScoresOV"]]), @@ -331,6 +332,44 @@ pcaResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( `type`="number", `format`="zto,pvalue", `superTitle`="Model Test"))))}))$new(options=options)) + self$add(R6::R6Class( + inherit = jmvcore::Group, + active = list( + corrAboveMin = function() private$.items[["corrAboveMin"]], + corrAboveMax = function() private$.items[["corrAboveMax"]]), + private = list(), + public=list( + initialize=function(options) { + super$initialize( + options=options, + name="dataSummary", + title="Data Summary") + self$add(jmvcore::Table$new( + options=options, + name="corrAboveMin", + title="Correlations Above Minimum Threshold", + visible="(minCorrThr > 0)", + rows=1, + clearWith=list( + "vars"), + columns=list( + list( + `name`="header", + `title`="", + `type`="text")))) + self$add(jmvcore::Table$new( + options=options, + name="corrAboveMax", + title="Correlations Above Maximum Threshold", + visible="(maxCorrThr > 0)", + rows=1, + clearWith=list( + "vars"), + columns=list( + list( + `name`="header", + `title`="", + `type`="text"))))}))$new(options=options)) self$add(R6::R6Class( inherit = jmvcore::Group, active = list( @@ -523,6 +562,8 @@ pcaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' \code{results$factorStats$factorSummary} \tab \tab \tab \tab \tab a table \cr #' \code{results$factorStats$factorCor} \tab \tab \tab \tab \tab a table \cr #' \code{results$modelFit$fit} \tab \tab \tab \tab \tab a table \cr +#' \code{results$dataSummary$corrAboveMin} \tab \tab \tab \tab \tab a table \cr +#' \code{results$dataSummary$corrAboveMax} \tab \tab \tab \tab \tab a table \cr #' \code{results$assump$bartlett} \tab \tab \tab \tab \tab a table \cr #' \code{results$assump$kmo} \tab \tab \tab \tab \tab a table \cr #' \code{results$eigen$initEigen} \tab \tab \tab \tab \tab a table \cr diff --git a/jamovi/efa.a.yaml b/jamovi/efa.a.yaml index 1b38f55b..5ee4026b 100644 --- a/jamovi/efa.a.yaml +++ b/jamovi/efa.a.yaml @@ -126,22 +126,22 @@ options: type: Number min: 0 max: 1 - default: 0.3 + default: 0 description: R: > - a number (default: 0.3), count correlations between variables that - are above this threshold + a number (default: 0), count correlations between variables that + are above this threshold (if 0, no output is produced) - name: maxCorrThr title: '' type: Number min: 0 max: 1 - default: 0.9 + default: 0 description: R: > - a number (default: 0.9), count correlations between variables that - are above this threshold + a number (default: 0), count correlations between variables that + are above this threshold (if 0, no output is produced) - name: kmo title: KMO measure of sampling adequacy diff --git a/jamovi/efa.u.yaml b/jamovi/efa.u.yaml index 313ab563..117f342a 100644 --- a/jamovi/efa.u.yaml +++ b/jamovi/efa.u.yaml @@ -66,6 +66,7 @@ children: enable: (nFactorMethod_fixed) - type: Label label: Data Summary + style: inline children: - name: minCorrThr type: TextBox diff --git a/jamovi/pca.r.yaml b/jamovi/pca.r.yaml index 16fb38a2..b7b9dcfc 100644 --- a/jamovi/pca.r.yaml +++ b/jamovi/pca.r.yaml @@ -123,6 +123,33 @@ items: format: zto,pvalue superTitle: Model Test + - name: dataSummary + title: Data Summary + type: Group + items: + - name: corrAboveMin + title: Correlations Above Minimum Threshold + type: Table + visible: (minCorrThr > 0) + rows: 1 + clearWith: + - vars + columns: + - name: header + title: "" + type: text + - name: corrAboveMax + title: Correlations Above Maximum Threshold + type: Table + visible: (maxCorrThr > 0) + rows: 1 + clearWith: + - vars + columns: + - name: header + title: "" + type: text + - name: assump title: Assumption Checks type: Group diff --git a/jamovi/pca.u.yaml b/jamovi/pca.u.yaml index 41b68bfb..b2382561 100644 --- a/jamovi/pca.u.yaml +++ b/jamovi/pca.u.yaml @@ -67,6 +67,7 @@ children: enable: (nFactorMethod_fixed) - type: Label label: Data Summary + style: inline children: - name: minCorrThr type: TextBox From 463a8e8e857ccb1d5d596876dbc4345091bcaa98 Mon Sep 17 00:00:00 2001 From: Sebastian Jentschke Date: Tue, 9 Sep 2025 18:02:17 +1000 Subject: [PATCH 3/5] Implemented Data Summary showing number of correlations above a minimum and maximum threshold --- R/efa.h.R | 46 ++++++++++++++++--------------- R/pca.b.R | 40 +++++++++++++++++++++++++-- R/pca.h.R | 70 +++++++++++++++++++++++++---------------------- jamovi/efa.a.yaml | 14 ++++------ jamovi/efa.u.yaml | 34 ++++++++++++++++++----- jamovi/pca.a.yaml | 20 +++++++------- jamovi/pca.r.yaml | 12 +++++--- jamovi/pca.u.yaml | 34 ++++++++++++++++++----- 8 files changed, 178 insertions(+), 92 deletions(-) diff --git a/R/efa.h.R b/R/efa.h.R index b0e15820..eb7656c4 100644 --- a/R/efa.h.R +++ b/R/efa.h.R @@ -12,8 +12,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = 0, extraction = "minres", rotation = "oblimin", - minCorrThr = 0, - maxCorrThr = 0, + countCorrMin = 0, + countCorrMax = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -77,15 +77,15 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="oblimin") - private$..minCorrThr <- jmvcore::OptionNumber$new( - "minCorrThr", - minCorrThr, + private$..countCorrMin <- jmvcore::OptionNumber$new( + "countCorrMin", + countCorrMin, min=0, max=1, default=0) - private$..maxCorrThr <- jmvcore::OptionNumber$new( - "maxCorrThr", - maxCorrThr, + private$..countCorrMax <- jmvcore::OptionNumber$new( + "countCorrMax", + countCorrMax, min=0, max=1, default=0) @@ -144,8 +144,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..minEigen) self$.addOption(private$..extraction) self$.addOption(private$..rotation) - self$.addOption(private$..minCorrThr) - self$.addOption(private$..maxCorrThr) + self$.addOption(private$..countCorrMin) + self$.addOption(private$..countCorrMax) self$.addOption(private$..kmo) self$.addOption(private$..bartlett) self$.addOption(private$..hideLoadings) @@ -165,8 +165,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = function() private$..minEigen$value, extraction = function() private$..extraction$value, rotation = function() private$..rotation$value, - minCorrThr = function() private$..minCorrThr$value, - maxCorrThr = function() private$..maxCorrThr$value, + countCorrMin = function() private$..countCorrMin$value, + countCorrMax = function() private$..countCorrMax$value, kmo = function() private$..kmo$value, bartlett = function() private$..bartlett$value, hideLoadings = function() private$..hideLoadings$value, @@ -185,8 +185,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..minEigen = NA, ..extraction = NA, ..rotation = NA, - ..minCorrThr = NA, - ..maxCorrThr = NA, + ..countCorrMin = NA, + ..countCorrMax = NA, ..kmo = NA, ..bartlett = NA, ..hideLoadings = NA, @@ -283,10 +283,12 @@ efaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'}, \code{'quartimax'}, #' \code{'promax'}, \code{'oblimin'} (default), or \code{'simplimax'}, the #' rotation to use in estimation -#' @param minCorrThr a number (default: 0), count correlations between -#' variables that are above this threshold (if 0, no output is produced) -#' @param maxCorrThr a number (default: 0), count correlations between -#' variables that are above this threshold (if 0, no output is produced) +#' @param countCorrMin a number (default: 0), returns the number of +#' correlations between variables above this minimum (if 0, no output is +#' produced) +#' @param countCorrMax a number (default: 0), returns the number of +#' correlations between variables above this maxmimum (if 0, no output is +#' produced) #' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin #' (KMO) measure of sampling adequacy (MSA) results #' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test @@ -321,8 +323,8 @@ efa <- function( minEigen = 0, extraction = "minres", rotation = "oblimin", - minCorrThr = 0, - maxCorrThr = 0, + countCorrMin = 0, + countCorrMax = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -352,8 +354,8 @@ efa <- function( minEigen = minEigen, extraction = extraction, rotation = rotation, - minCorrThr = minCorrThr, - maxCorrThr = maxCorrThr, + countCorrMin = countCorrMin, + countCorrMax = countCorrMax, kmo = kmo, bartlett = bartlett, hideLoadings = hideLoadings, diff --git a/R/pca.b.R b/R/pca.b.R index e423b4a8..9a6c4b37 100644 --- a/R/pca.b.R +++ b/R/pca.b.R @@ -110,14 +110,13 @@ pcaClass <- R6::R6Class( private$.initLoadingsTable() private$.initModelFitTable() private$.initEigenTable() + private$.initCorrCountTable() private$.initKMOTable() private$.initFactorCor() }, .run = function() { if (is.null(self$options$vars) || length(self$options$vars) < 2) return() -print(self$options$minCorrThr) -print(self$options$maxCorrThr) private$.errorCheck() @@ -126,6 +125,7 @@ print(self$options$maxCorrThr) private$.populateFactorSummaryTable() private$.populateFactorCorTable() private$.populateModelFitTable() + private$.populateCorrCountTable() private$.populateKMOTable() private$.populateBartlettTable() private$.prepareScreePlot() @@ -252,6 +252,21 @@ print(self$options$maxCorrThr) for (i in seq_along(self$options$vars)) table$addRow(rowKey=i, values=list(comp = as.character(i))) }, + .initCorrCountTable = function() { + group <- self$results$dataSummary + vars <- self$options$vars + + for (t in c("Min", "Max")) { + table <- group[[paste0("corrAbove", t)]] + title <- jmvcore::format(.("Correlations Above {} Threshold ({})"), + ifelse(t == "Min", .("Minimum"), .("Maximum")), + self$options[[paste0("countCorr", t)]]) + table$setTitle(title) + for (i in seq_along(vars)) { + table$addColumn(name = sprintf("c%d", i), title = ".", type = 'integer') + } + } + }, .initKMOTable = function() { table <- self$results$assump$kmo vars <- self$options$vars @@ -415,6 +430,27 @@ print(self$options$maxCorrThr) table$setRow(rowNo=1, values=row) } }, + .populateCorrCountTable = function() { + group <- self$results$dataSummary + vars <- self$options$vars + if (length(vars) >= 1) { + corrMatrix = abs(cor(sapply(self$data[, vars], jmvcore::toNumeric), use = "pairwise")) + diag(corrMatrix) <- NA + + for (t in c("Min", "Max")) { + thresh <- self$options[[paste0("countCorr", t)]] + if (thresh > 0) { + table <- group[[paste0("corrAbove", t)]] + counts <- sort(colSums(corrMatrix > thresh, na.rm = TRUE)) + cnames <- names(counts) + table$setRow(rowNo = 1, setNames(as.list(counts), sprintf("c%d", seq_along(vars)))) + for (i in seq_along(cnames)) { + table$columns[[i + 1]]$setTitle(cnames[i]) + } + } + } + } + }, .populateKMOTable = function() { if (! self$options$kmo) return() diff --git a/R/pca.h.R b/R/pca.h.R index 3c062f8c..2a3cff42 100644 --- a/R/pca.h.R +++ b/R/pca.h.R @@ -11,8 +11,8 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( nFactors = 1, minEigen = 1, rotation = "varimax", - minCorrThr = 0.3, - maxCorrThr = 0.9, + countCorrMin = 0, + countCorrMax = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -66,18 +66,18 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="varimax") - private$..minCorrThr <- jmvcore::OptionNumber$new( - "minCorrThr", - minCorrThr, + private$..countCorrMin <- jmvcore::OptionNumber$new( + "countCorrMin", + countCorrMin, min=0, max=1, - default=0.3) - private$..maxCorrThr <- jmvcore::OptionNumber$new( - "maxCorrThr", - maxCorrThr, + default=0) + private$..countCorrMax <- jmvcore::OptionNumber$new( + "countCorrMax", + countCorrMax, min=0, max=1, - default=0.9) + default=0) private$..kmo <- jmvcore::OptionBool$new( "kmo", kmo, @@ -118,8 +118,8 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..nFactors) self$.addOption(private$..minEigen) self$.addOption(private$..rotation) - self$.addOption(private$..minCorrThr) - self$.addOption(private$..maxCorrThr) + self$.addOption(private$..countCorrMin) + self$.addOption(private$..countCorrMax) self$.addOption(private$..kmo) self$.addOption(private$..bartlett) self$.addOption(private$..hideLoadings) @@ -136,8 +136,8 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( nFactors = function() private$..nFactors$value, minEigen = function() private$..minEigen$value, rotation = function() private$..rotation$value, - minCorrThr = function() private$..minCorrThr$value, - maxCorrThr = function() private$..maxCorrThr$value, + countCorrMin = function() private$..countCorrMin$value, + countCorrMax = function() private$..countCorrMax$value, kmo = function() private$..kmo$value, bartlett = function() private$..bartlett$value, hideLoadings = function() private$..hideLoadings$value, @@ -153,8 +153,8 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..nFactors = NA, ..minEigen = NA, ..rotation = NA, - ..minCorrThr = NA, - ..maxCorrThr = NA, + ..countCorrMin = NA, + ..countCorrMax = NA, ..kmo = NA, ..bartlett = NA, ..hideLoadings = NA, @@ -347,29 +347,33 @@ pcaResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$add(jmvcore::Table$new( options=options, name="corrAboveMin", - title="Correlations Above Minimum Threshold", - visible="(minCorrThr > 0)", + title="", + visible="(countCorrMin > 0)", rows=1, clearWith=list( - "vars"), + "vars", + "countCorrMin"), columns=list( list( `name`="header", `title`="", - `type`="text")))) + `type`="text", + `content`="N")))) self$add(jmvcore::Table$new( options=options, name="corrAboveMax", - title="Correlations Above Maximum Threshold", - visible="(maxCorrThr > 0)", + title="", + visible="(countCorrMax > 0)", rows=1, clearWith=list( - "vars"), + "vars", + "countCorrMax"), columns=list( list( `name`="header", `title`="", - `type`="text"))))}))$new(options=options)) + `type`="text", + `content`="N"))))}))$new(options=options)) self$add(R6::R6Class( inherit = jmvcore::Group, active = list( @@ -539,10 +543,12 @@ pcaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'} (default), #' \code{'quartimax'}, \code{'promax'}, \code{'oblimin'}, or #' \code{'simplimax'}, the rotation to use in estimation -#' @param minCorrThr a number (default: 0.3), count correlations between -#' variables that are above this threshold -#' @param maxCorrThr a number (default: 0.9), count correlations between -#' variables that are above this threshold +#' @param countCorrMin a number (default: 0), returns the number of +#' correlations between variables above this minimum (if 0, no output is +#' produced) +#' @param countCorrMax a number (default: 0), returns the number of +#' correlations between variables above this maxmimum (if 0, no output is +#' produced) #' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin #' (KMO) measure of sampling adequacy (MSA) results #' @param bartlett \code{TRUE} or \code{FALSE} (default), show Bartlett's test @@ -585,8 +591,8 @@ pca <- function( nFactors = 1, minEigen = 1, rotation = "varimax", - minCorrThr = 0.3, - maxCorrThr = 0.9, + countCorrMin = 0, + countCorrMax = 0, kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -613,8 +619,8 @@ pca <- function( nFactors = nFactors, minEigen = minEigen, rotation = rotation, - minCorrThr = minCorrThr, - maxCorrThr = maxCorrThr, + countCorrMin = countCorrMin, + countCorrMax = countCorrMax, kmo = kmo, bartlett = bartlett, hideLoadings = hideLoadings, diff --git a/jamovi/efa.a.yaml b/jamovi/efa.a.yaml index 5ee4026b..f555c190 100644 --- a/jamovi/efa.a.yaml +++ b/jamovi/efa.a.yaml @@ -121,27 +121,25 @@ options: `'oblimin'` (default), or `'simplimax'`, the rotation to use in estimation - - name: minCorrThr - title: '' + - name: countCorrMin type: Number min: 0 max: 1 default: 0 description: R: > - a number (default: 0), count correlations between variables that - are above this threshold (if 0, no output is produced) + a number (default: 0), returns the number of correlations between + variables above this minimum (if 0, no output is produced) - - name: maxCorrThr - title: '' + - name: countCorrMax type: Number min: 0 max: 1 default: 0 description: R: > - a number (default: 0), count correlations between variables that - are above this threshold (if 0, no output is produced) + a number (default: 0), returns the number of correlations between + variables above this maxmimum (if 0, no output is produced) - name: kmo title: KMO measure of sampling adequacy diff --git a/jamovi/efa.u.yaml b/jamovi/efa.u.yaml index 117f342a..a2754971 100644 --- a/jamovi/efa.u.yaml +++ b/jamovi/efa.u.yaml @@ -66,14 +66,34 @@ children: enable: (nFactorMethod_fixed) - type: Label label: Data Summary - style: inline children: - - name: minCorrThr - type: TextBox - format: number - - name: maxCorrThr - type: TextBox - format: number + - type: Label + label: Count Correlations Above Min. + cell: + column: 0 + row: 0 + - type: LayoutBox + cell: + column: 1 + row: 0 + children: + - name: countCorrMin + type: TextBox + format: number + - type: Label + label: And Above Max. + horizontalAlignment: right + cell: + column: 0 + row: 1 + - type: LayoutBox + cell: + column: 1 + row: 1 + children: + - name: countCorrMax + type: TextBox + format: number - type: LayoutBox margin: large cell: diff --git a/jamovi/pca.a.yaml b/jamovi/pca.a.yaml index 9b535272..57c2331a 100644 --- a/jamovi/pca.a.yaml +++ b/jamovi/pca.a.yaml @@ -101,27 +101,27 @@ options: `'oblimin'`, or `'simplimax'`, the rotation to use in estimation - - name: minCorrThr - title: '' + - name: countCorrMin + title: "" type: Number min: 0 max: 1 - default: 0.3 + default: 0 description: R: > - a number (default: 0.3), count correlations between variables that - are above this threshold + a number (default: 0), returns the number of correlations between + variables above this minimum (if 0, no output is produced) - - name: maxCorrThr - title: '' + - name: countCorrMax + title: "" type: Number min: 0 max: 1 - default: 0.9 + default: 0 description: R: > - a number (default: 0.9), count correlations between variables that - are above this threshold + a number (default: 0), returns the number of correlations between + variables above this maxmimum (if 0, no output is produced) - name: kmo title: KMO measure of sampling adequacy diff --git a/jamovi/pca.r.yaml b/jamovi/pca.r.yaml index b7b9dcfc..351166e6 100644 --- a/jamovi/pca.r.yaml +++ b/jamovi/pca.r.yaml @@ -128,27 +128,31 @@ items: type: Group items: - name: corrAboveMin - title: Correlations Above Minimum Threshold + title: "" type: Table - visible: (minCorrThr > 0) + visible: (countCorrMin > 0) rows: 1 clearWith: - vars + - countCorrMin columns: - name: header title: "" type: text + content: N - name: corrAboveMax - title: Correlations Above Maximum Threshold + title: "" type: Table - visible: (maxCorrThr > 0) + visible: (countCorrMax > 0) rows: 1 clearWith: - vars + - countCorrMax columns: - name: header title: "" type: text + content: N - name: assump title: Assumption Checks diff --git a/jamovi/pca.u.yaml b/jamovi/pca.u.yaml index b2382561..261b2946 100644 --- a/jamovi/pca.u.yaml +++ b/jamovi/pca.u.yaml @@ -67,14 +67,34 @@ children: enable: (nFactorMethod_fixed) - type: Label label: Data Summary - style: inline children: - - name: minCorrThr - type: TextBox - format: number - - name: maxCorrThr - type: TextBox - format: number + - type: Label + label: Count Correlations Above Min. + cell: + column: 0 + row: 0 + - type: LayoutBox + cell: + column: 1 + row: 0 + children: + - name: countCorrMin + type: TextBox + format: number + - type: Label + label: And Above Max. + horizontalAlignment: right + cell: + column: 0 + row: 1 + - type: LayoutBox + cell: + column: 1 + row: 1 + children: + - name: countCorrMax + type: TextBox + format: number - type: LayoutBox margin: large cell: From 5f3ece5282a38a0f4e5ccda465367ffac851ef7f Mon Sep 17 00:00:00 2001 From: Sebastian Jentschke Date: Wed, 10 Sep 2025 08:29:57 +1000 Subject: [PATCH 4/5] Implemented Data Summary showing number of correlations above a minimum and maximum threshold --- R/efa.h.R | 28 ++++++++++++---------------- R/pca.b.R | 21 +++++++++++---------- R/pca.h.R | 32 ++++++++++++++------------------ jamovi/efa.a.yaml | 20 ++++++++------------ jamovi/efa.u.yaml | 4 ++-- jamovi/pca.a.yaml | 20 ++++++++------------ jamovi/pca.r.yaml | 4 ++-- jamovi/pca.u.yaml | 4 ++-- 8 files changed, 59 insertions(+), 74 deletions(-) diff --git a/R/efa.h.R b/R/efa.h.R index eb7656c4..20a4a167 100644 --- a/R/efa.h.R +++ b/R/efa.h.R @@ -12,8 +12,8 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( minEigen = 0, extraction = "minres", rotation = "oblimin", - countCorrMin = 0, - countCorrMax = 0, + countCorrMin = "", + countCorrMax = "", kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -77,18 +77,14 @@ efaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="oblimin") - private$..countCorrMin <- jmvcore::OptionNumber$new( + private$..countCorrMin <- jmvcore::OptionString$new( "countCorrMin", countCorrMin, - min=0, - max=1, - default=0) - private$..countCorrMax <- jmvcore::OptionNumber$new( + default="") + private$..countCorrMax <- jmvcore::OptionString$new( "countCorrMax", countCorrMax, - min=0, - max=1, - default=0) + default="") private$..kmo <- jmvcore::OptionBool$new( "kmo", kmo, @@ -283,11 +279,11 @@ efaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'}, \code{'quartimax'}, #' \code{'promax'}, \code{'oblimin'} (default), or \code{'simplimax'}, the #' rotation to use in estimation -#' @param countCorrMin a number (default: 0), returns the number of -#' correlations between variables above this minimum (if 0, no output is +#' @param countCorrMin a number (default: NA), returns the number of +#' correlations between variables above this minimum (if NA, no output is #' produced) -#' @param countCorrMax a number (default: 0), returns the number of -#' correlations between variables above this maxmimum (if 0, no output is +#' @param countCorrMax a number (default: NA), returns the number of +#' correlations between variables above this maxmimum (if NA, no output is #' produced) #' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin #' (KMO) measure of sampling adequacy (MSA) results @@ -323,8 +319,8 @@ efa <- function( minEigen = 0, extraction = "minres", rotation = "oblimin", - countCorrMin = 0, - countCorrMax = 0, + countCorrMin = "", + countCorrMax = "", kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, diff --git a/R/pca.b.R b/R/pca.b.R index 9a6c4b37..23cadbee 100644 --- a/R/pca.b.R +++ b/R/pca.b.R @@ -263,7 +263,7 @@ pcaClass <- R6::R6Class( self$options[[paste0("countCorr", t)]]) table$setTitle(title) for (i in seq_along(vars)) { - table$addColumn(name = sprintf("c%d", i), title = ".", type = 'integer') + table$addColumn(name = sprintf("c%d", i), title = "", type = 'integer') } } }, @@ -438,15 +438,16 @@ pcaClass <- R6::R6Class( diag(corrMatrix) <- NA for (t in c("Min", "Max")) { - thresh <- self$options[[paste0("countCorr", t)]] - if (thresh > 0) { - table <- group[[paste0("corrAbove", t)]] - counts <- sort(colSums(corrMatrix > thresh, na.rm = TRUE)) - cnames <- names(counts) - table$setRow(rowNo = 1, setNames(as.list(counts), sprintf("c%d", seq_along(vars)))) - for (i in seq_along(cnames)) { - table$columns[[i + 1]]$setTitle(cnames[i]) - } + thresh <- as.numeric(self$options[[paste0("countCorr", t)]]) + if (is.na(thresh)) next + if (thresh <= 0 || thresh >= 1) + jmvcore::reject(.("Values for the Correlation Min. / Max. need to be Numeric and Between 0 and 1")) + table <- group[[paste0("corrAbove", t)]] + counts <- sort(colSums(corrMatrix > thresh, na.rm = TRUE)) + cnames <- names(counts) + table$setRow(rowNo = 1, setNames(as.list(counts), sprintf("c%d", seq_along(vars)))) + for (i in seq_along(cnames)) { + table$columns[[i + 1]]$setTitle(cnames[i]) } } } diff --git a/R/pca.h.R b/R/pca.h.R index 2a3cff42..1f89ffa1 100644 --- a/R/pca.h.R +++ b/R/pca.h.R @@ -11,8 +11,8 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( nFactors = 1, minEigen = 1, rotation = "varimax", - countCorrMin = 0, - countCorrMax = 0, + countCorrMin = "", + countCorrMax = "", kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, @@ -66,18 +66,14 @@ pcaOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "oblimin", "simplimax"), default="varimax") - private$..countCorrMin <- jmvcore::OptionNumber$new( + private$..countCorrMin <- jmvcore::OptionString$new( "countCorrMin", countCorrMin, - min=0, - max=1, - default=0) - private$..countCorrMax <- jmvcore::OptionNumber$new( + default="") + private$..countCorrMax <- jmvcore::OptionString$new( "countCorrMax", countCorrMax, - min=0, - max=1, - default=0) + default="") private$..kmo <- jmvcore::OptionBool$new( "kmo", kmo, @@ -348,7 +344,7 @@ pcaResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( options=options, name="corrAboveMin", title="", - visible="(countCorrMin > 0)", + visible="(countCorrMin != \"\")", rows=1, clearWith=list( "vars", @@ -363,7 +359,7 @@ pcaResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( options=options, name="corrAboveMax", title="", - visible="(countCorrMax > 0)", + visible="(countCorrMax != \"\")", rows=1, clearWith=list( "vars", @@ -543,11 +539,11 @@ pcaBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' @param rotation \code{'none'}, \code{'varimax'} (default), #' \code{'quartimax'}, \code{'promax'}, \code{'oblimin'}, or #' \code{'simplimax'}, the rotation to use in estimation -#' @param countCorrMin a number (default: 0), returns the number of -#' correlations between variables above this minimum (if 0, no output is +#' @param countCorrMin a number (default: NA), returns the number of +#' correlations between variables above this minimum (if NA, no output is #' produced) -#' @param countCorrMax a number (default: 0), returns the number of -#' correlations between variables above this maxmimum (if 0, no output is +#' @param countCorrMax a number (default: NA), returns the number of +#' correlations between variables above this maxmimum (if NA, no output is #' produced) #' @param kmo \code{TRUE} or \code{FALSE} (default), show Kaiser-Meyer-Olkin #' (KMO) measure of sampling adequacy (MSA) results @@ -591,8 +587,8 @@ pca <- function( nFactors = 1, minEigen = 1, rotation = "varimax", - countCorrMin = 0, - countCorrMax = 0, + countCorrMin = "", + countCorrMax = "", kmo = FALSE, bartlett = FALSE, hideLoadings = 0.3, diff --git a/jamovi/efa.a.yaml b/jamovi/efa.a.yaml index f555c190..09370645 100644 --- a/jamovi/efa.a.yaml +++ b/jamovi/efa.a.yaml @@ -122,24 +122,20 @@ options: in estimation - name: countCorrMin - type: Number - min: 0 - max: 1 - default: 0 + type: String + default: "" description: R: > - a number (default: 0), returns the number of correlations between - variables above this minimum (if 0, no output is produced) + a number (default: NA), returns the number of correlations between + variables above this minimum (if NA, no output is produced) - name: countCorrMax - type: Number - min: 0 - max: 1 - default: 0 + type: String + default: "" description: R: > - a number (default: 0), returns the number of correlations between - variables above this maxmimum (if 0, no output is produced) + a number (default: NA), returns the number of correlations between + variables above this maxmimum (if NA, no output is produced) - name: kmo title: KMO measure of sampling adequacy diff --git a/jamovi/efa.u.yaml b/jamovi/efa.u.yaml index a2754971..855ba5f2 100644 --- a/jamovi/efa.u.yaml +++ b/jamovi/efa.u.yaml @@ -79,7 +79,7 @@ children: children: - name: countCorrMin type: TextBox - format: number + format: string - type: Label label: And Above Max. horizontalAlignment: right @@ -93,7 +93,7 @@ children: children: - name: countCorrMax type: TextBox - format: number + format: string - type: LayoutBox margin: large cell: diff --git a/jamovi/pca.a.yaml b/jamovi/pca.a.yaml index 57c2331a..2c65e9c9 100644 --- a/jamovi/pca.a.yaml +++ b/jamovi/pca.a.yaml @@ -103,25 +103,21 @@ options: - name: countCorrMin title: "" - type: Number - min: 0 - max: 1 - default: 0 + type: String + default: "" description: R: > - a number (default: 0), returns the number of correlations between - variables above this minimum (if 0, no output is produced) + a number (default: NA), returns the number of correlations between + variables above this minimum (if NA, no output is produced) - name: countCorrMax title: "" - type: Number - min: 0 - max: 1 - default: 0 + type: String + default: "" description: R: > - a number (default: 0), returns the number of correlations between - variables above this maxmimum (if 0, no output is produced) + a number (default: NA), returns the number of correlations between + variables above this maxmimum (if NA, no output is produced) - name: kmo title: KMO measure of sampling adequacy diff --git a/jamovi/pca.r.yaml b/jamovi/pca.r.yaml index 351166e6..c6507e76 100644 --- a/jamovi/pca.r.yaml +++ b/jamovi/pca.r.yaml @@ -130,7 +130,7 @@ items: - name: corrAboveMin title: "" type: Table - visible: (countCorrMin > 0) + visible: (countCorrMin != "") rows: 1 clearWith: - vars @@ -143,7 +143,7 @@ items: - name: corrAboveMax title: "" type: Table - visible: (countCorrMax > 0) + visible: (countCorrMax != "") rows: 1 clearWith: - vars diff --git a/jamovi/pca.u.yaml b/jamovi/pca.u.yaml index 261b2946..db0651bf 100644 --- a/jamovi/pca.u.yaml +++ b/jamovi/pca.u.yaml @@ -80,7 +80,7 @@ children: children: - name: countCorrMin type: TextBox - format: number + format: string - type: Label label: And Above Max. horizontalAlignment: right @@ -94,7 +94,7 @@ children: children: - name: countCorrMax type: TextBox - format: number + format: string - type: LayoutBox margin: large cell: From 16e78956a72a62f893ecb9f47aa2fd79285d519c Mon Sep 17 00:00:00 2001 From: Sebastian Jentschke Date: Fri, 24 Oct 2025 14:06:42 +1100 Subject: [PATCH 5/5] Fixed sorting the correlation counts --- R/pca.b.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/pca.b.R b/R/pca.b.R index 23cadbee..d2370f3f 100644 --- a/R/pca.b.R +++ b/R/pca.b.R @@ -443,7 +443,9 @@ pcaClass <- R6::R6Class( if (thresh <= 0 || thresh >= 1) jmvcore::reject(.("Values for the Correlation Min. / Max. need to be Numeric and Between 0 and 1")) table <- group[[paste0("corrAbove", t)]] - counts <- sort(colSums(corrMatrix > thresh, na.rm = TRUE)) + # sort the columns by the number of correlations above threshold (increasing for min: lower counts + # on the left, decreasing for max: higher counts on the left) + counts <- sort(colSums(corrMatrix > thresh, na.rm = TRUE), decreasing = (t == "Max")) cnames <- names(counts) table$setRow(rowNo = 1, setNames(as.list(counts), sprintf("c%d", seq_along(vars)))) for (i in seq_along(cnames)) {