diff --git a/.gitignore b/.gitignore index da28c61..8642cbb 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ cran-comments.md Rplots.pdf references/working/ .claude/ +.claude/settings.local.json diff --git a/NAMESPACE b/NAMESPACE index c0c6ec5..a233aee 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -134,6 +134,7 @@ importFrom(stats,qlogis) importFrom(stats,qnorm) importFrom(stats,qt) importFrom(stats,quantile) +importFrom(stats,runif) importFrom(stats,sd) importFrom(stats,setNames) importFrom(stats,t.test) diff --git a/R/boot_ses_test.R b/R/boot_ses_test.R index 5c773ca..759be38 100644 --- a/R/boot_ses_test.R +++ b/R/boot_ses_test.R @@ -177,6 +177,7 @@ #' bootstrap confidence intervals, [brunner_munzel()] with #' `test_method = "perm"` for robust TOST on the probability scale. #' @name boot_ses_test +#' @importFrom stats runif #' @export boot_ses_test boot_ses_test <- function(x, ..., diff --git a/R/compare_cor.R b/R/compare_cor.R index 881a540..f22e57a 100644 --- a/R/compare_cor.R +++ b/R/compare_cor.R @@ -39,13 +39,19 @@ #' * For minimal effect testing ("minimal.effect"), it determines whether the difference falls #' outside the specified bounds. #' +#' **Note on Fisher's z transformation of bounds:** When `method = "fisher"`, the `null` values +#' (equivalence bounds) are specified on the **correlation scale** and are internally converted to +#' the Fisher z scale via `atanh()`. For example, `null = 0.4` is treated as r = 0.4, which maps +#' to z = 0.4236. If you want bounds expressed directly in Fisher-z units, you should back-transform +#' them to the correlation scale first using `tanh()` before passing them to this function. +#' #' When performing equivalence or minimal effect testing: #' * If a single value is provided for `null`, symmetric bounds ±value will be used #' * If two values are provided for `null`, they will be used as the lower and upper bounds #' #' @return A list with class "htest" containing the following components: #' -#' * **statistic**: z-score with name "z" +#' * **statistic**: standardized z-score (i.e., the test statistic divided by its standard error) with name "z" #' * **p.value**: numeric scalar containing the p-value for the test under the null hypothesis #' * **estimate**: difference in correlation coefficients between studies #' * **null.value**: the specified hypothesized value(s) for the null hypothesis @@ -138,10 +144,10 @@ compare_cor = function(r1, phi = p_from_z(zhi/z_se, alternative = 'less') if(phi >= plo){ pval = phi - z = zhi + z = zhi / z_se } else { pval = plo - z = zlo + z = zlo / z_se } } if(alternative == "minimal.effect"){ @@ -151,10 +157,10 @@ compare_cor = function(r1, phi = p_from_z(zhi/z_se, alternative = 'greater') if(phi <= plo){ pval = phi - z = zhi + z = zhi / z_se } else { pval = plo - z = zlo + z = zlo / z_se } } } else { @@ -178,10 +184,10 @@ compare_cor = function(r1, phi = p_from_z(zhi/se, alternative = 'less') if(phi >= plo){ pval = phi - z = zhi + z = zhi / se } else { pval = plo - z = zlo + z = zlo / se } } if(alternative == "minimal.effect"){ @@ -191,10 +197,10 @@ compare_cor = function(r1, phi = p_from_z(zhi/se, alternative = 'greater') if(phi <= plo){ pval = phi - z = zhi + z = zhi / se } else { pval = plo - z = zlo + z = zlo / se } } } else{ diff --git a/man/compare_cor.Rd b/man/compare_cor.Rd index e677781..ec11411 100644 --- a/man/compare_cor.Rd +++ b/man/compare_cor.Rd @@ -50,7 +50,7 @@ or a vector of two values representing the lower and upper bounds \value{ A list with class "htest" containing the following components: \itemize{ -\item \strong{statistic}: z-score with name "z" +\item \strong{statistic}: standardized z-score (i.e., the test statistic divided by its standard error) with name "z" \item \strong{p.value}: numeric scalar containing the p-value for the test under the null hypothesis \item \strong{estimate}: difference in correlation coefficients between studies \item \strong{null.value}: the specified hypothesized value(s) for the null hypothesis @@ -93,6 +93,12 @@ the specified bounds, which can be set asymmetrically. outside the specified bounds. } +\strong{Note on Fisher's z transformation of bounds:} When \code{method = "fisher"}, the \code{null} values +(equivalence bounds) are specified on the \strong{correlation scale} and are internally converted to +the Fisher z scale via \code{atanh()}. For example, \code{null = 0.4} is treated as r = 0.4, which maps +to z = 0.4236. If you want bounds expressed directly in Fisher-z units, you should back-transform +them to the correlation scale first using \code{tanh()} before passing them to this function. + When performing equivalence or minimal effect testing: \itemize{ \item If a single value is provided for \code{null}, symmetric bounds ±value will be used diff --git a/tests/testthat/test-corr.R b/tests/testthat/test-corr.R index 0fada6a..cf9a376 100644 --- a/tests/testthat/test-corr.R +++ b/tests/testthat/test-corr.R @@ -388,6 +388,29 @@ test_that("Run examples for boot_cor_test", { }) +test_that("compare_cor: z-statistic is standardized (issue #115)", { + result <- compare_cor( + r1 = 0.6, df1 = 18, + r2 = 0.8, df2 = 23, + null = 0.4, + method = "fisher", + alternative = "equivalence" + ) + + # Manually compute the expected standardized z + z1 <- atanh(0.6) + z2 <- atanh(0.8) + diff <- z1 - z2 + SE <- sqrt(1/17 + 1/22) + bound_z <- atanh(0.4) + + expected_z <- (diff - (-bound_z)) / SE + expected_p <- 1 - pnorm(expected_z) + + expect_equal(unname(result$statistic), expected_z, tolerance = 1e-6) + expect_equal(result$p.value, expected_p, tolerance = 1e-6) +}) + test_that("Run examples for boot_compare_cor", { skip_on_cran()