diff --git a/R/ttestis.b.R b/R/ttestis.b.R index 2ba38a58..7554571e 100644 --- a/R/ttestis.b.R +++ b/R/ttestis.b.R @@ -18,6 +18,8 @@ ttestISClass <- R6::R6Class( data[[name]] <- jmvcore::toNumeric(data[[name]]) data[[groupVarName]] <- droplevels(as.factor(data[[groupVarName]])) + testValue <- self$options$get("testValue") + ttestTable <- self$results$ttest descTable <- self$results$desc normTable <- self$results$assum$get('norm') @@ -26,6 +28,8 @@ ttestISClass <- R6::R6Class( confInt <- self$options$ciWidth / 100 confIntES <- 1 - self$options$ciWidthES / 100 + + if (any(depVarNames == groupVarName)) jmvcore::reject("Grouping variable '{a}' must not also be a dependent variable", code="a_is_dependent_variable", a=groupVarName) @@ -78,8 +82,8 @@ ttestISClass <- R6::R6Class( sediffSTUD <- tryNaN(sqrt((pooledVARSTUD/n[1])+(pooledVARSTUD/n[2]))) sediffWELC <- tryNaN(sqrt((v[1]/n[1])+(v[2]/n[2]))) - dSTUD <- (m[1]-m[2])/sqrt(pooledVARSTUD) # Cohen's d for student's t - dWELC <- (m[1]-m[2])/sqrt(pooledVARWELC) # Cohen's d for Welch's t + dSTUD <- (m[1]-m[2] - testValue)/sqrt(pooledVARSTUD) # Cohen's d for student's t + dWELC <- (m[1]-m[2] - testValue)/sqrt(pooledVARWELC) # Cohen's d for Welch's t dCISTUD <- psych::d.ci(dSTUD, n1=n[1], n2=n[2], alpha=confIntES) dCIWELC <- psych::d.ci(dWELC, n1=n[1], n2=n[2], alpha=confIntES) @@ -96,7 +100,10 @@ ttestISClass <- R6::R6Class( ## Levene's test and equality of variances table - levene <- try(car::leveneTest(dep ~ group, data=dataTTest, "mean"), silent=TRUE) + levene <- try(car::leveneTest(dep ~ group, + data=dataTTest, + "mean"), + silent=TRUE) if (isError(levene)) { @@ -125,8 +132,14 @@ ttestISClass <- R6::R6Class( else if (any(is.infinite(dataTTest$dep))) res <- createError('Variable contains infinite values') else - res <- try(t.test(dep ~ group, data=dataTTest, var.equal=TRUE, paired=FALSE, - alternative=Ha, conf.level=confInt), silent=TRUE) + res <- try(t.test(dep ~ group, + data = dataTTest, + var.equal = TRUE, + paired = FALSE, + alternative = Ha, + conf.level = confInt, + mu = testValue), + silent = TRUE) if (isError(res)) { @@ -158,10 +171,10 @@ ttestISClass <- R6::R6Class( "stat[stud]"=res$statistic, "df[stud]"=res$parameter, "p[stud]"=res$p.value, - "md[stud]"=res$estimate[1]-res$estimate[2], + "md[stud]"=res$estimate[1]-res$estimate[2] - testValue, "sed[stud]"=sediffSTUD, - "cil[stud]"=res$conf.int[1], - "ciu[stud]"=res$conf.int[2], + "cil[stud]"=res$conf.int[1] - testValue, + "ciu[stud]"=res$conf.int[2] - testValue, "es[stud]"=dSTUD, "ciles[stud]"=dCISTUD[1], "ciues[stud]"=dCISTUD[3])) @@ -180,8 +193,14 @@ ttestISClass <- R6::R6Class( else if (any(is.infinite(dataTTest$dep))) res <- createError('Variable contains infinite values') else - res <- try(t.test(dep ~ group, data=dataTTest, var.equal=FALSE, paired=FALSE, - alternative=Ha, conf.level=confInt), silent=TRUE) + res <- try(t.test(dep ~ group, + data=dataTTest, + var.equal=FALSE, + paired=FALSE, + alternative=Ha, + conf.level=confInt, + mu = testValue), + silent=TRUE) if ( ! isError(res)) { @@ -189,10 +208,10 @@ ttestISClass <- R6::R6Class( "stat[welc]"=res$statistic, "df[welc]"=res$parameter, "p[welc]"=res$p.value, - "md[welc]"=res$estimate[1]-res$estimate[2], + "md[welc]"=res$estimate[1]-res$estimate[2] - testValue, "sed[welc]"=sediffWELC, - "cil[welc]"=res$conf.int[1], - "ciu[welc]"=res$conf.int[2], + "cil[welc]"=res$conf.int[1] - testValue, + "ciu[welc]"=res$conf.int[2] - testValue, "es[welc]"=dWELC, "ciles[welc]"='', "ciues[welc]"='')) @@ -258,7 +277,8 @@ ttestISClass <- R6::R6Class( alternative=Ha1, paired=FALSE, conf.int=TRUE, - conf.level=confInt) + conf.level=confInt, + mu = testValue) ), silent=TRUE) res2 <- try(suppressWarnings( @@ -268,14 +288,15 @@ ttestISClass <- R6::R6Class( alternative=Ha2, paired=FALSE, conf.int=TRUE, - conf.level=confInt) + conf.level=confInt, + mu = testValue) ), silent=TRUE) m1 <- res$statistic m2 <- res2$statistic - mm <- res$estimate - cil <- res$conf.int[1] - ciu <- res$conf.int[2] + mm <- res$estimate - testValue + cil <- res$conf.int[1] - testValue + ciu <- res$conf.int[2] - testValue if ( ! is.na(m1) && m2 < m1) res <- res2 @@ -395,8 +416,12 @@ ttestISClass <- R6::R6Class( rscale <- self$options$bfPrior - res <- try(BayesFactor::ttestBF(formula=dep ~ group, data=dataTTest, paired=FALSE, - nullInterval=nullInterval, rscale=rscale), silent=TRUE) + res <- try(BayesFactor::ttestBF(formula=dep ~ group, + data=dataTTest, + paired=FALSE, + nullInterval=nullInterval, + rscale=rscale), + silent=TRUE) } if (isError(res)) { @@ -433,6 +458,12 @@ ttestISClass <- R6::R6Class( if ( ! is.na(bf) && bf < 1) ttestTable$addFormat(col='stat[bf]', rowKey=depName, Cell.NEGATIVE) } + # Inform that Bayes Factor doesn't allow for setting mu at this time + if (testValue != 0) + ttestTable$addFootnote(rowKey=depName, "stat[bf]", + "Use of nonzero null hypothesis not implemented for Bayes Factor. Result is of Test Value = 0") + + } if (self$options$qq) { @@ -483,6 +514,7 @@ ttestISClass <- R6::R6Class( .init=function() { hypothesis <- self$options$hypothesis + testValue <- self$options$get('testValue') groupName <- self$options$group groups <- NULL @@ -514,11 +546,11 @@ ttestISClass <- R6::R6Class( table$getColumn('ciles[mann]')$setSuperTitle(ciTitleES) if (hypothesis == 'oneGreater') - table$setNote("hyp", jmvcore::format("H\u2090 {} > {}", groups[1], groups[2])) + table$setNote("hyp", jmvcore::format("H\u2090 {} - {} > {}", groups[1], groups[2],testValue)) else if (hypothesis == 'twoGreater') - table$setNote("hyp", jmvcore::format("H\u2090 {} < {}", groups[1], groups[2])) + table$setNote("hyp", jmvcore::format("H\u2090 {} - {} < {}", groups[1], groups[2],testValue)) else - table$setNote("hyp", NULL) + table$setNote("hyp", jmvcore::format("H\u2090 {} - {} \u2260 {}", groups[1], groups[2],testValue)) }, .desc=function(image, ggtheme, theme, ...) { diff --git a/R/ttestis.h.R b/R/ttestis.h.R index 6164daf7..9b1cec8a 100644 --- a/R/ttestis.h.R +++ b/R/ttestis.h.R @@ -13,6 +13,7 @@ ttestISOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( bfPrior = 0.707, welchs = FALSE, mann = FALSE, + testValue = 0, hypothesis = "different", norm = FALSE, qq = FALSE, @@ -71,6 +72,10 @@ ttestISOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "mann", mann, default=FALSE) + private$..testValue <- jmvcore::OptionNumber$new( + "testValue", + testValue, + default=0) private$..hypothesis <- jmvcore::OptionList$new( "hypothesis", hypothesis, @@ -142,6 +147,7 @@ ttestISOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..bfPrior) self$.addOption(private$..welchs) self$.addOption(private$..mann) + self$.addOption(private$..testValue) self$.addOption(private$..hypothesis) self$.addOption(private$..norm) self$.addOption(private$..qq) @@ -164,6 +170,7 @@ ttestISOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( bfPrior = function() private$..bfPrior$value, welchs = function() private$..welchs$value, mann = function() private$..mann$value, + testValue = function() private$..testValue$value, hypothesis = function() private$..hypothesis$value, norm = function() private$..norm$value, qq = function() private$..qq$value, @@ -185,6 +192,7 @@ ttestISOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..bfPrior = NA, ..welchs = NA, ..mann = NA, + ..testValue = NA, ..hypothesis = NA, ..norm = NA, ..qq = NA, @@ -223,6 +231,7 @@ ttestISResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( clearWith=list( "group", "hypothesis", + "testValue", "ciWidth", "miss", "bfPrior", @@ -774,6 +783,7 @@ ttestISBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' t-tests #' @param mann \code{TRUE} or \code{FALSE} (default), perform Mann-Whitney U #' tests +#' @param testValue a number specifying the value of the null hypothesis #' @param hypothesis \code{'different'} (default), \code{'oneGreater'} or #' \code{'twoGreater'}, the alternative hypothesis; group 1 different to group #' 2, group 1 greater than group 2, and group 2 greater than group 1 @@ -830,6 +840,7 @@ ttestIS <- function( bfPrior = 0.707, welchs = FALSE, mann = FALSE, + testValue = 0, hypothesis = "different", norm = FALSE, qq = FALSE, @@ -881,6 +892,7 @@ ttestIS <- function( bfPrior = bfPrior, welchs = welchs, mann = mann, + testValue = testValue, hypothesis = hypothesis, norm = norm, qq = qq, diff --git a/R/ttestps.b.R b/R/ttestps.b.R index abaf4a35..82e67edd 100644 --- a/R/ttestps.b.R +++ b/R/ttestps.b.R @@ -6,6 +6,7 @@ ttestPSClass <- R6::R6Class( .run=function() { data <- self$data + testValue <- self$options$get("testValue") ttestTable <- self$results$get('ttest') descTable <- self$results$get('desc') @@ -64,7 +65,7 @@ ttestPSClass <- R6::R6Class( pooledSD <- tryNaN(stats::sd(column1-column2)) sediff <- pooledSD/sqrt(n) - d <- (m1-m2)/pooledSD #Cohen's d + d <- (m1-m2-testValue)/pooledSD #Cohen's d dCI <- psych::d.ci(d, n1=n, alpha=confIntES) if (is.factor(column1) || is.factor(column2)) { @@ -72,8 +73,20 @@ ttestPSClass <- R6::R6Class( wilc <- createError('One or both variables are not numeric') } else { - stud <- try(t.test(column1, column2, paired=TRUE, conf.level=confInt, alternative=Ha), silent=TRUE) - wilc <- try(suppressWarnings(wilcox.test(column1, column2, alternative=Ha, paired=TRUE, conf.int=TRUE, conf.level=confInt)), silent=TRUE) + stud <- try(t.test(column1, column2, + paired=TRUE, + conf.level=confInt, + alternative=Ha, + mu=testValue), + silent=TRUE) + wilc <- try(suppressWarnings(wilcox.test(column1, + column2, + alternative=Ha, + paired=TRUE, + conf.int=TRUE, + conf.level=confInt, + mu=testValue)), + silent=TRUE) } if ( ! isError(stud)) { @@ -82,10 +95,10 @@ ttestPSClass <- R6::R6Class( 'stat[stud]'=stud$statistic, 'df[stud]'=stud$parameter, 'p[stud]'=stud$p.value, - 'md[stud]'=stud$estimate, + 'md[stud]'=stud$estimate - testValue, 'sed[stud]'=sediff, - 'cil[stud]'=stud$conf.int[1], - 'ciu[stud]'=stud$conf.int[2], + 'cil[stud]'=stud$conf.int[1] - testValue, + 'ciu[stud]'=stud$conf.int[2] - testValue, 'es[stud]'=d, "ciles[stud]"=dCI[1], "ciues[stud]"=dCI[3])) @@ -121,10 +134,10 @@ ttestPSClass <- R6::R6Class( 'stat[wilc]'=wilc$statistic, 'df[wilc]'=wilc$parameter, 'p[wilc]'=wilc$p.value, - 'md[wilc]'=wilc$estimate, + 'md[wilc]'=wilc$estimate - testValue, 'sed[wilc]'=sediff, - 'cil[wilc]'=wilc$conf.int[1], - 'ciu[wilc]'=wilc$conf.int[2], + 'cil[wilc]'=wilc$conf.int[1] - testValue, + 'ciu[wilc]'=wilc$conf.int[2] - testValue, 'es[wilc]'=biSerial, "ciles[wilc]"='', "ciues[wilc]"='')) @@ -224,7 +237,12 @@ ttestPSClass <- R6::R6Class( rscale <- self$options$get('bfPrior') - res <- try(BayesFactor::ttestBF(x=column1, y=column2, paired=TRUE, nullInterval=nullInterval, rscale=rscale), silent=TRUE) + res <- try(BayesFactor::ttestBF(x=column1, + y=column2, + paired=TRUE, + nullInterval=nullInterval, + mu = testValue, + rscale=rscale), silent=TRUE) } if (isError(res)) { @@ -300,6 +318,7 @@ ttestPSClass <- R6::R6Class( .init=function() { hypothesis <- self$options$get('hypothesis') + testValue <- self$options$get("testValue") ttestTable <- self$results$get('ttest') ciTitle <- paste0(self$options$get('ciWidth'), '% Confidence Interval') @@ -320,13 +339,6 @@ ttestPSClass <- R6::R6Class( ttestTable$getColumn('ciues[wilc]')$setSuperTitle(ciTitleES) ttestTable$getColumn('ciles[wilc]')$setSuperTitle(ciTitleES) - if (hypothesis == 'oneGreater') - ttestTable$setNote("hyp", "H\u2090 Measure 1 > Measure 2") - else if (hypothesis == 'twoGreater') - ttestTable$setNote("hyp", "H\u2090 Measure 1 < Measure 2") - else - ttestTable$setNote("hyp", NULL) - pairs <- self$options$pairs descTable <- self$results$desc @@ -351,6 +363,19 @@ ttestPSClass <- R6::R6Class( plots$get(pair)$setTitle(paste0(pair, collapse=' - ')) } + + + + if (self$options$get("hypothesis") == 'oneGreater') { + ttestTable$setNote("hyp", jmvcore::format("H\u2090 Measure 1 - Measure 2 > {}", testValue)) + } else if (self$options$get("hypothesis") == 'twoGreater'){ + ttestTable$setNote("hyp", jmvcore::format("H\u2090 Measure 1 - Measure 2 < {}", testValue)) + } else { + ttestTable$setNote("hyp", jmvcore::format("H\u2090 Measure 1 - Measure 2 \u2260 {}", testValue)) + } + + + }, .desc=function(image, ggtheme, theme, ...) { diff --git a/R/ttestps.h.R b/R/ttestps.h.R index dcbcd96b..636fd322 100644 --- a/R/ttestps.h.R +++ b/R/ttestps.h.R @@ -11,6 +11,7 @@ ttestPSOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( bf = FALSE, bfPrior = 0.707, wilcoxon = FALSE, + testValue = 0, hypothesis = "different", norm = FALSE, qq = FALSE, @@ -55,6 +56,10 @@ ttestPSOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( "wilcoxon", wilcoxon, default=FALSE) + private$..testValue <- jmvcore::OptionNumber$new( + "testValue", + testValue, + default=0) private$..hypothesis <- jmvcore::OptionList$new( "hypothesis", hypothesis, @@ -120,6 +125,7 @@ ttestPSOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( self$.addOption(private$..bf) self$.addOption(private$..bfPrior) self$.addOption(private$..wilcoxon) + self$.addOption(private$..testValue) self$.addOption(private$..hypothesis) self$.addOption(private$..norm) self$.addOption(private$..qq) @@ -139,6 +145,7 @@ ttestPSOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( bf = function() private$..bf$value, bfPrior = function() private$..bfPrior$value, wilcoxon = function() private$..wilcoxon$value, + testValue = function() private$..testValue$value, hypothesis = function() private$..hypothesis$value, norm = function() private$..norm$value, qq = function() private$..qq$value, @@ -157,6 +164,7 @@ ttestPSOptions <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( ..bf = NA, ..bfPrior = NA, ..wilcoxon = NA, + ..testValue = NA, ..hypothesis = NA, ..norm = NA, ..qq = NA, @@ -194,6 +202,7 @@ ttestPSResults <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( clearWith=list( "miss", "hypothesis", + "testValue", "ciWidth", "bfPrior", "ciWidthES"), @@ -613,6 +622,7 @@ ttestPSBase <- if (requireNamespace("jmvcore", quietly=TRUE)) R6::R6Class( #' to use in calculating Bayes factors #' @param wilcoxon \code{TRUE} or \code{FALSE} (default), perform Wilcoxon #' signed rank tests +#' @param testValue a number specifying the value of the null hypothesis #' @param hypothesis \code{'different'} (default), \code{'oneGreater'} or #' \code{'twoGreater'}, the alternative hypothesis; measure 1 different to #' measure 2, measure 1 greater than measure 2, and measure 2 greater than @@ -663,6 +673,7 @@ ttestPS <- function( bf = FALSE, bfPrior = 0.707, wilcoxon = FALSE, + testValue = 0, hypothesis = "different", norm = FALSE, qq = FALSE, @@ -690,6 +701,7 @@ ttestPS <- function( bf = bf, bfPrior = bfPrior, wilcoxon = wilcoxon, + testValue = testValue, hypothesis = hypothesis, norm = norm, qq = qq, diff --git a/jamovi/ttestis.a.yaml b/jamovi/ttestis.a.yaml index 86ea1925..ec379b21 100644 --- a/jamovi/ttestis.a.yaml +++ b/jamovi/ttestis.a.yaml @@ -139,6 +139,14 @@ options: R: > `TRUE` or `FALSE` (default), perform Mann-Whitney U tests + - name: testValue + title: Test Value + type: Number + default: 0 + description: + ui: the test value to test against (typically zero). + R: a number specifying the value of the null hypothesis + - name: hypothesis title: Alternative hypothesis type: List diff --git a/jamovi/ttestis.r.yaml b/jamovi/ttestis.r.yaml index 8045ca34..fcb9e131 100644 --- a/jamovi/ttestis.r.yaml +++ b/jamovi/ttestis.r.yaml @@ -12,6 +12,7 @@ items: clearWith: - group - hypothesis + - testValue - ciWidth - miss - bfPrior diff --git a/jamovi/ttestis.u.yaml b/jamovi/ttestis.u.yaml index 7545af8a..6ad9291d 100644 --- a/jamovi/ttestis.u.yaml +++ b/jamovi/ttestis.u.yaml @@ -1,6 +1,6 @@ -name: ttestIS +name: ttestIS title: Independent Samples T-Test -jus: '2.0' +jus: '2.0' compilerMode: tame children: - type: VariableSupplier @@ -28,8 +28,8 @@ children: children: - type: LayoutBox cell: - column: 0 - row: 0 + column: 0 + row: 0 stretchFactor: 1 children: - type: Label @@ -47,34 +47,34 @@ children: label: Prior format: number enable: (bf) - - type: CheckBox name: welchs - - type: CheckBox name: mann - - type: Label label: Hypothesis children: + - type: LayoutBox + children: + - type: TextBox + name: testValue + label: Test value + format: number - type: RadioButton name: hypothesis_different optionName: hypothesis optionPart: different - label: "Group 1 ≠ Group 2" - + label: Group 1 - Group 2 ≠ Test value - type: RadioButton name: hypothesis_oneGreater optionName: hypothesis optionPart: oneGreater - label: "Group 1 > Group 2" - + label: Group 1 - Group 2 > Test value - type: RadioButton name: hypothesis_twoGreater optionName: hypothesis optionPart: twoGreater - label: "Group 1 < Group 2" - + label: Group 1 - Group 2 < Test value - type: Label label: Missing values children: @@ -83,17 +83,15 @@ children: optionName: miss optionPart: perAnalysis label: Exclude cases analysis by analysis - - type: RadioButton name: miss_listwise optionName: miss optionPart: listwise label: Exclude cases listwise - - type: LayoutBox cell: - column: 1 - row: 0 + column: 1 + row: 0 stretchFactor: 1 children: - type: Label @@ -105,56 +103,51 @@ children: children: - type: LayoutBox children: - - type: CheckBox - name: ci - label: Confidence interval - enable: (meanDiff) - style: inline - verticalAlignment: center - children: - - type: TextBox - name: ciWidth - label: "" - suffix: "%" - format: number - enable: (meanDiff && ci) - + - type: CheckBox + name: ci + label: Confidence interval + enable: (meanDiff) + style: inline + verticalAlignment: center + children: + - type: TextBox + name: ciWidth + label: '' + suffix: '%' + format: number + enable: (meanDiff && ci) - type: CheckBox name: effectSize label: Effect size children: - type: LayoutBox children: - - type: CheckBox - name: ciES - label: Confidence interval - enable: (effectSize) - style: inline - verticalAlignment: center - children: - - type: TextBox - name: ciWidthES - label: "" - suffix: "%" - format: number - enable: (effectSize && ciES) - + - type: CheckBox + name: ciES + label: Confidence interval + enable: (effectSize) + style: inline + verticalAlignment: center + children: + - type: TextBox + name: ciWidthES + label: '' + suffix: '%' + format: number + enable: (effectSize && ciES) - type: CheckBox name: desc label: Descriptives - - type: CheckBox name: plots label: Descriptives plots - - type: Label label: Assumption Checks children: - type: CheckBox name: eqv - - type: CheckBox name: norm - - type: CheckBox name: qq + diff --git a/jamovi/ttestps.a.yaml b/jamovi/ttestps.a.yaml index 8e85379f..9897408a 100644 --- a/jamovi/ttestps.a.yaml +++ b/jamovi/ttestps.a.yaml @@ -103,6 +103,14 @@ options: R: > `TRUE` or `FALSE` (default), perform Wilcoxon signed rank tests + - name: testValue + title: Test Value + type: Number + default: 0 + description: + ui: the test value to test against (typically zero). + R: a number specifying the value of the null hypothesis + - name: hypothesis title: Alternative hypothesis type: List diff --git a/jamovi/ttestps.r.yaml b/jamovi/ttestps.r.yaml index 1f4e6ce9..843ffd48 100644 --- a/jamovi/ttestps.r.yaml +++ b/jamovi/ttestps.r.yaml @@ -12,6 +12,7 @@ items: clearWith: - miss - hypothesis + - testValue - ciWidth - bfPrior - ciWidthES diff --git a/jamovi/ttestps.u.yaml b/jamovi/ttestps.u.yaml index 472f7602..e86e5f2b 100644 --- a/jamovi/ttestps.u.yaml +++ b/jamovi/ttestps.u.yaml @@ -59,21 +59,27 @@ children: - type: Label label: Hypothesis children: + - type: LayoutBox + children: + - type: TextBox + name: testValue + label: Test value + format: number - type: RadioButton name: hypothesis_different optionName: hypothesis optionPart: different - label: Measure 1 ≠ Measure 2 + label: Measure 1 - Measure 2 ≠ Test value - type: RadioButton name: hypothesis_oneGreater optionName: hypothesis optionPart: oneGreater - label: Measure 1 > Measure 2 + label: Measure 1 - Measure 2 > Test value - type: RadioButton name: hypothesis_twoGreater optionName: hypothesis optionPart: twoGreater - label: Measure 1 < Measure 2 + label: Measure 1 - Measure 2 < Test value - type: Label label: Missing values children: