diff --git a/DESCRIPTION b/DESCRIPTION index c134e1b5..90be8308 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: metafor -Version: 4.7-34 -Date: 2024-09-30 +Version: 4.7-35 +Date: 2024-10-15 Title: Meta-Analysis Package for R Authors@R: person(given = "Wolfgang", family = "Viechtbauer", role = c("aut","cre"), email = "wvb@metafor-project.org", comment = c(ORCID = "0000-0003-3463-4063")) Depends: R (>= 4.0.0), methods, Matrix, metadat, numDeriv diff --git a/NEWS.md b/NEWS.md index e6485747..7959459f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,4 @@ -# metafor 4.7-34 (2024-09-30) +# metafor 4.7-35 (2024-10-15) - some general changes to the various `forest()` functions: argument `header` is now `TRUE` by default, the y-axis is now created with `yaxs="i"`, and the y-axis limits have been tweaked slightly in accordance @@ -36,7 +36,7 @@ - `nobs()` now just returns the number of estimates, not the effective number of observations -- added measure `"PRZ"` to `escalc()` +- added measures `"PRZ"`, `"CLES"`, `"AUC"`, `"CLESN"`, and `"AUCN"` to `escalc()` - `escalc()` gains a `flip` argument @@ -46,6 +46,8 @@ - added transformation function `transf.dtoovl()` (for transforming standardized mean differences to overlapping coefficient values) and ``transf.dtocliffd()` (for transforming standardized mean differences to Cliff's delta values) +- `escalc()` gains a `correct` argument (to specify whether a bias correction should be applied) + - better handling of `outlist="minimal"` - added more tests diff --git a/R/escalc.r b/R/escalc.r index ab09d784..d1816623 100644 --- a/R/escalc.r +++ b/R/escalc.r @@ -1,5 +1,5 @@ escalc <- function(measure, ai, bi, ci, di, n1i, n2i, x1i, x2i, t1i, t2i, m1i, m2i, sd1i, sd2i, xi, mi, ri, ti, fi, pi, sdi, r2i, ni, yi, vi, sei, -data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS", var.names=c("yi","vi"), add.measure=FALSE, append=TRUE, replace=TRUE, digits, ...) { +data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS", correct=TRUE, var.names=c("yi","vi"), add.measure=FALSE, append=TRUE, replace=TRUE, digits, ...) { ### check argument specifications @@ -29,7 +29,7 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" "MN","SMN","MNLN","CVLN","SDLN", # mean, single-group standardized mean, log(mean), log(CV), log(SD), "MC","SMCC","SMCR","SMCRH","SMCRP","SMCRPH","ROMC","CVRC","VRC", # raw/standardized mean change, log(ROM), CVR, and VR for dependent samples "ARAW","AHW","ABT", # alpha (and transformations thereof) - "REH",#"AUC", # relative excess heterozygosity, area under the curve + "REH","CLES","CLESN","AUC","AUCN", # relative excess heterozygosity, common language effect size / area under the curve "HR","HD", # hazard (rate) ratios and differences "GEN"))) stop(mstyle$stop("Unknown 'measure' specified.")) @@ -39,7 +39,7 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" if (!is.element(to, c("all","only0","if0all","none"))) stop(mstyle$stop("Unknown 'to' argument specified.")) - if (any(!is.element(vtype, c("UB","LS","LS2","LS3","HO","ST","CS","AV","AV2","AVHO")), na.rm=TRUE)) # vtype can be an entire vector, so use any() and na.rm=TRUE + if (any(!is.element(vtype, c("UB","LS","LS2","LS3","HO","ST","CS","AV","AV2","AVHO","H0","MAX")), na.rm=TRUE)) # vtype can be an entire vector, so use any() and na.rm=TRUE stop(mstyle$stop("Unknown 'vtype' argument specified.")) if (add.measure) { @@ -80,14 +80,13 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" ddd <- list(...) - .chkdots(ddd, c("onlyo1", "addyi", "addvi", "correct")) + .chkdots(ddd, c("onlyo1", "addyi", "addvi")) - ### set defaults or get onlyo1, addyi, addvi, and correct arguments + ### set defaults or get onlyo1, addyi, and addvi arguments onlyo1 <- .chkddd(ddd$onlyo1, FALSE, .isTRUE(ddd$onlyo1)) addyi <- .chkddd(ddd$addyi, TRUE, .isTRUE(ddd$addyi)) addvi <- .chkddd(ddd$addvi, TRUE, .isTRUE(ddd$addvi)) - correct <- .chkddd(ddd$correct, TRUE, .isTRUE(ddd$correct)) ### set defaults for digits @@ -1044,8 +1043,12 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" for (i in seq_len(k)) { ### estimate of the sampling variance for fixed n1i and n2i (i.e., stratified sampling) - if (vtype[i] == "ST" || vtype[i] == "LS") + if (vtype[i] == "ST" || vtype[i] == "LS") { vi[i] <- hi[i]^2 / (hi[i] + di[i]^2)^3 * (1/n1i[i] + 1/n2i[i] + di[i]^2/(2*ni[i])) + # this is consistent with escalc(measure="SMD", correct=FALSE) -> conv.delta(transf=transf.dtorpb) + #tmp <- escalc(measure="SMD", m1i=m1i[i], sd1i=sd1i[i], n1i=n1i[i], m2i=m2i[i], sd2i=sd2i[i], n2i=n2i[i], correct=FALSE) + #vi[i] <- conv.delta(yi, vi, data=tmp, transf=transf.dtorpb, replace=TRUE, n1i=n1i[i], n2i=n2i[i])$vi + } ### estimate of the sampling variance for fixed ni but random n1i and n2i (i.e., cross-sectional/multinomial sampling) if (vtype[i] == "CS") @@ -1067,9 +1070,13 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" yi <- sqrt(p1i*p2i) / fzi * yi # yi on the right-hand side is the point-biserial correlation from above #vi <- (p1i*p2i) / fzi^2 * vi # not correct (p1i, p2i, and fzi are random variables and vi from RBP is not correct for the bivariate normal case on which RBIS is based) yi.t <- ifelse(abs(yi) > 1, sign(yi), yi) - vi <- 1/(ni-1) * (p1i*p2i/fzi^2 - (3/2 + (1 - p1i*zi/fzi)*(1 + p2i*zi/fzi)) * yi.t^2 + yi.t^4) # Soper, 1914 + vi <- 1/(ni-0) * (p1i*p2i/fzi^2 - (3/2 + (1 - p1i*zi/fzi)*(1 + p2i*zi/fzi)) * yi.t^2 + yi.t^4) # Soper, 1914 #vi <- 1/(ni-1) * (yi.t^4 + yi.t^2 * (p1i*p2i*zi^2/fzi^2 + (2*p1i-1)*zi/fzi - 5/2) + p1i*p2i/fzi^2) # Tate, 1955; equivalent to equation from Soper, 1914 # equation appears to work even if dichotomization is done based on a sample quantile value (so that p1i, p2i, and fzi are fixed by design) + # this is asymptotically consistent with escalc(measure="SMD", correct=FALSE) -> conv.delta(transf=transf.dtorbis) + #tmp <- escalc(measure="SMD", m1i=m1i, sd1i=sd1i, n1i=n1i, m2i=m2i, sd2i=sd2i, n2i=n2i, correct=FALSE) + #yi <- conv.delta(yi, vi, data=tmp, transf=transf.dtorbis, replace=TRUE, n1i=n1i, n2i=n2i)$yi + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.dtorbis, replace=TRUE, n1i=n1i, n2i=n2i)$vi } ### r-to-z transformation for RPB and RBIS (note: NOT a variance-stabilizing transformation for these measures) @@ -1096,14 +1103,22 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" ### coefficient of variation ratio if (measure == "CVR") { - yi <- log(sd1i/m1i) + 1/(2*(n1i-1)) - log(sd2i/m2i) - 1/(2*(n2i-1)) + if (correct) { + yi <- log(sd1i/m1i) + 1/(2*(n1i-1)) - log(sd2i/m2i) - 1/(2*(n2i-1)) + } else { + yi <- log(sd1i/m1i) - log(sd2i/m2i) + } vi <- 1/(2*(n1i-1)) + sd1i^2/(n1i*m1i^2) + 1/(2*(n2i-1)) + sd2i^2/(n2i*m2i^2) # Nakagawa et al., 2015, equation 12, but without the '-2 rho ...' terms } ### variability ratio if (measure == "VR") { - yi <- log(sd1i/sd2i) + 1/(2*(n1i-1)) - 1/(2*(n2i-1)) + if (correct) { + yi <- log(sd1i/sd2i) + 1/(2*(n1i-1)) - 1/(2*(n2i-1)) + } else { + yi <- log(sd1i/sd2i) + } vi <- 1/(2*(n1i-1)) + 1/(2*(n2i-1)) } @@ -1705,6 +1720,9 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" if (measure == "PRZ") { yi <- qnorm(pri) vi <- 2*base::pi*pri*(1-pri)*exp(yi^2)/ni + # this is consistent with escalc(measure="PR") -> conv.delta(transf=qnorm) + #tmp <- escalc(measure="PR", xi=xi, ni=ni) + #vi <- conv.delta(yi, vi, data=tmp, transf=qnorm, replace=TRUE)$vi } ### proportion with arcsine square root (angular) transformation @@ -1712,13 +1730,19 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" if (measure == "PAS") { yi <- asin(sqrt(pri)) vi <- 1/(4*ni) + # this is consistent with escalc(measure="PR") -> conv.delta(transf=transf.arcsin) + #tmp <- escalc(measure="PR", xi=xi, ni=ni) + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.arcsin, replace=TRUE)$vi } ### proportion with Freeman-Tukey double arcsine transformation if (measure == "PFT") { yi <- 1/2*(asin(sqrt(xi/(ni+1))) + asin(sqrt((xi+1)/(ni+1)))) - vi <- 1/(4*ni + 2) + vi <- 1/(4*ni+2) + # this is asymptotically consistent with escalc(measure="PR") -> conv.delta(transf=transf.pft) + #tmp <- escalc(measure="PR", xi=xi, ni=ni) + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.pft, ni=ni, replace=TRUE)$vi } } @@ -1837,6 +1861,9 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" yi <- sqrt(iri.u) } vi <- 1 / (4*ti) + # this is consistent with escalc(measure="IR") -> conv.delta(transf=sqrt) + #tmp <- escalc(measure="IR", xi=xi, ti=ti) + #vi <- conv.delta(yi, vi, data=tmp, transf=sqrt, replace=TRUE)$vi } ### note: addyi and addvi only implemented for measures above @@ -1846,6 +1873,9 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" if (measure == "IRFT") { yi <- 1/2 * (sqrt(iri) + sqrt(iri+1/ti)) vi <- 1 / (4*ti) + # this is asymptotically consistent with escalc(measure="IR") -> conv.delta(transf=transf.irft) + #tmp <- escalc(measure="IR", xi=xi, ti=ti) + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.irft, ti=ti, replace=TRUE)$vi } } @@ -1935,7 +1965,7 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" ### single-group standardized mean if (measure == "SMN") { - cmi <- .cmicalc(ni-1) + cmi <- .cmicalc(ni-1, correct=correct) yi <- cmi * mi / sdi vi <- 1 / ni + yi^2 / (2*ni) } @@ -2327,6 +2357,10 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" #yi <- (1-ai)^(1/3) # technically this is the Hakstian & Whalen (1976) transformation yi <- 1 - (1-ai)^(1/3) # but with this, yi remains a monotonically increasing function of ai vi <- 18*mi*(ni-1)*(1-ai)^(2/3) / ((mi-1)*(9*ni-11)^2) + #vi <- 2*mi*(1-ai)^(2/3) / (9*(mi-1)*(ni-2)) # this follows from the delta method + # this is asymptotically consistent with escalc(measure="ARAW") -> conv.delta(transf=transf.ahw) + #tmp <- escalc(measure="ARAW", ai=ai, mi=mi, ni=ni) + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.ahw, replace=TRUE)$vi } ### alphas transformed with Bonett (2002) transformation (without bias correction) @@ -2336,6 +2370,9 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" #yi <- log(1-ai) # technically this is the Bonett (2002) transformation yi <- -log(1-ai) # but with this, yi remains a monotonically increasing function of ai vi <- 2*mi / ((mi-1)*(ni-2)) + # this is consistent with escalc(measure="ARAW") -> conv.delta(transf=transf.abt) + #tmp <- escalc(measure="ARAW", ai=ai, mi=mi, ni=ni) + #vi <- conv.delta(yi, vi, data=tmp, transf=transf.abt, replace=TRUE)$vi } } @@ -2383,6 +2420,222 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" ###################################################################### + if (is.element(measure, c("CLES","AUC"))) { + + ai <- .getx("ai", mf=mf, data=data, checknumeric=TRUE) + n1i <- .getx("n1i", mf=mf, data=data, checknumeric=TRUE) + n2i <- .getx("n2i", mf=mf, data=data, checknumeric=TRUE) + mi <- .getx("mi", mf=mf, data=data, checknumeric=TRUE) + + if (!.all.specified(ai, n1i, n2i)) + stop(mstyle$stop("Cannot compute outcomes. Check that all of the required information is specified\n via the appropriate arguments (i.e., ai, n1i, n2i).")) + + if (!.equal.length(ai, n1i, n2i, mi)) + stop(mstyle$stop("Supplied data vectors are not all of the same length.")) + + if (is.null(mi)) + mi <- rep(0, length(ai)) + + mi[is.na(mi)] <- 0 + + k.all <- length(ai) + + if (!is.null(subset)) { + subset <- .chksubset(subset, k.all) + ai <- .getsubset(ai, subset) + n1i <- .getsubset(n1i, subset) + n2i <- .getsubset(n2i, subset) + mi <- .getsubset(mi, subset) + } + + if (any(c(n1i, n2i) <= 0, na.rm=TRUE)) + stop(mstyle$stop("One or more group sizes are <= 0.")) + + if (any(ai < 0, na.rm=TRUE) || any(ai > 1, na.rm=TRUE)) + stop(mstyle$stop("One or more AUC values are < 0 or > 1.")) + + if (any(mi < 0, na.rm=TRUE) || any(mi > 1, na.rm=TRUE)) + stop(mstyle$stop("One or more 'mi' values are < 0 or > 1.")) + + ni <- n1i + n2i + + ni.u <- ni # unadjusted total sample sizes + + k <- length(ai) + + yi <- ai + + vtype <- .expand1(vtype, k) + + vi <- rep(NA_real_, k) + + navgi <- (n1i+n2i)/2 + q0 <- ai*(1-ai) + q1 <- ai/(2-ai) + q2 <- 2*ai^2/(1+ai) + + if (!all(is.element(vtype, c("LS","LS2","H0","MAX")))) + stop(mstyle$stop("For this outcome measure, 'vtype' must be 'LS' or 'LS2'.")) + + for (i in seq_len(k)) { + + ### based on Newcombe (2006b) but using (n1i-1)*(n2i-1) in the denominator as given in Cho et al. (2019), section 2.4 + if (vtype[i] == "LS") + vi[i] <- q0[i] / ((n1i[i]-1)*(n2i[i]-1)) * (2*navgi[i] - 1 - (3*navgi[i]-3) / ((2-ai[i])*(1+ai[i]))) + + ### based on Hanley and McNeil (1982) but using (n1i-1)*(n2i-1) in the denominator and subtracting mi/4 as given in Cho et al. (2019) + if (vtype[i] == "LS2") + vi[i] <- (q0[i] - mi[i]/4 + (n1i[i]-1)*(q1[i]-ai[i]^2) + (n2i[i]-1)*(q2[i]-ai[i]^2)) / ((n1i[i]-1)*(n2i[i]-1)) + + ### under H0: CLES=AUC=0.5 and equal variances (conservative if there are ties) + if (vtype[i] == "H0") + vi[i] <- (n1i[i]+n2i[i]+1)/(12*n1i[i]*n2i[i]) + + ### based on sigma^2_max (eq. 7 in Bamber, 1975) + if (vtype[i] == "MAX") + vi[i] <- q0[i] / (min(n1i[i],n2i[i])-1) + + } + + } + + if (is.element(measure, c("CLESN","AUCN"))) { + + m1i <- .getx("m1i", mf=mf, data=data, checknumeric=TRUE) + m2i <- .getx("m2i", mf=mf, data=data, checknumeric=TRUE) + sd1i <- .getx("sd1i", mf=mf, data=data, checknumeric=TRUE) + sd2i <- .getx("sd2i", mf=mf, data=data, checknumeric=TRUE) + n1i <- .getx("n1i", mf=mf, data=data, checknumeric=TRUE) + n2i <- .getx("n2i", mf=mf, data=data, checknumeric=TRUE) + di <- .getx("di", mf=mf, data=data, checknumeric=TRUE) + ti <- .getx("ti", mf=mf, data=data, checknumeric=TRUE) + pi <- .getx("pi", mf=mf, data=data, checknumeric=TRUE) + ai <- .getx("ai", mf=mf, data=data, checknumeric=TRUE) + + if (!.equal.length(m1i, m2i, sd1i, sd2i, n1i, n2i, di, ti, pi, ai)) + stop(mstyle$stop("Supplied data vectors are not all of the same length.")) + + if (!.all.specified(n1i, n2i)) + stop(mstyle$stop("Cannot compute outcomes. Check that all of the required information is specified\n via the appropriate arguments.")) + + k.all <- max(sapply(list(m1i, m2i, sd1i, sd2i, n1i, n2i, di, ti, pi, ai), length)) + + vtype <- .expand1(vtype, k.all) + + ### if sd1i and/or sd2i have not been specified at all, set sd1i and sd2i to NA for all studies + + if (is.null(sd1i) || is.null(sd2i)) { + sd1i <- .expand1(NA_real_, k.all) + sd2i <- .expand1(NA_real_, k.all) + } + + ### convert pi to ti values + + ti <- replmiss(ti, .convp2t(pi, df=n1i+n2i-2)) + + ### convert ti to di values + + di <- replmiss(di, ti * sqrt(1/n1i + 1/n2i)) + + ### for specified pi/ti/di values, assume homoscedasticity + + if (!is.null(di)) + vtype[!is.na(di)] <- "HO" + + ### compute di values from means and SDs (for these, do not assume homoscedasticity, unless vtype="HO") + + sdpi <- ifelse(vtype=="HO", sqrt(((n1i-1)*sd1i^2 + (n2i-1)*sd2i^2)/(n1i+n2i-2)), sqrt((sd1i^2 + sd2i^2)/2)) + di <- replmiss(di, (m1i - m2i) / sdpi) + + ### convert di values to ai values and back (in case only ai is known, so we have di for computing vi) + + ai <- replmiss(ai, pnorm(di/sqrt(2))) + di <- replmiss(di, qnorm(ai)*sqrt(2)) + + k.all <- length(ai) + + ### if sd1i and/or sd2i is missing for a particular study, assume sd1i=sd2i=1 for that study and homoscedasticity + + sdsmiss <- is.na(sd1i) | is.na(sd2i) + sd1i <- ifelse(sdsmiss, 1, sd1i) + sd2i <- ifelse(sdsmiss, 1, sd2i) + vtype[sdsmiss] <- "HO" + + if (!is.null(subset)) { + subset <- .chksubset(subset, k.all) + vtype <- .getsubset(vtype, subset) + ai <- .getsubset(ai, subset) + di <- .getsubset(di, subset) + sd1i <- .getsubset(sd1i, subset) + sd2i <- .getsubset(sd2i, subset) + n1i <- .getsubset(n1i, subset) + n2i <- .getsubset(n2i, subset) + } + + if (any(c(sd1i, sd2i) < 0, na.rm=TRUE)) + stop(mstyle$stop("One or more standard deviations are negative.")) + + if (any(c(n1i, n2i) <= 0, na.rm=TRUE)) + stop(mstyle$stop("One or more group sizes are <= 0.")) + + if (any(ai < 0, na.rm=TRUE) || any(ai > 1, na.rm=TRUE)) + stop(mstyle$stop("One or more AUC values are < 0 or > 1.")) + + ni.u <- n1i + n2i # unadjusted total sample sizes + + k <- length(ai) + + ni <- ni.u + + yi <- ai + + vi <- rep(NA_real_, k) + + if (!all(is.element(vtype, c("LS","LS2","LS3","HO")))) + stop(mstyle$stop("For this outcome measure, 'vtype' must be 'LS' or 'HO'.")) + + vri <- sd1i^2 / (sd1i^2 + sd2i^2) + + for (i in seq_len(k)) { + + ### large sample approximation to the sampling variance based on the binormal model + if (vtype[i] == "LS") { + vi[i] <- exp(-di[i]^2 / 2) / (8*base::pi) * (di[i]^2 * vri[i]^2 / (n1i[i]-1) + di[i]^2 * (1-vri[i])^2 / (n2i[i]-1) + 4*vri[i]/(n1i[i]-1) + 4*(1-vri[i])/(n2i[i]-1)) + # this is consistent with escalc(measure="SMDH", correct=FALSE) -> conv.delta(transf=transf.dtocles) + #tmp <- escalc(measure="SMDH", m1i=m1i[i], sd1i=sd1i[i], n1i=n1i[i], m2i=m2i[i], sd2i=sd2i[i], n2i=n2i[i], correct=FALSE) + #vi[i] <- conv.delta(yi, vi, data=tmp, transf=transf.dtocles, replace=TRUE)$vi + } + + ### large sample approximation to the sampling variance based on the binormal model + if (vtype[i] == "LS2") { + vi[i] <- exp(-di[i]^2 / 2) / (8*base::pi) * (di[i]^2 * vri[i]^2 / (n1i[i]-0) + di[i]^2 * (1-vri[i])^2 / (n2i[i]-0) + 4*vri[i]/(n1i[i]-0) + 4*(1-vri[i])/(n2i[i]-0)) + # this is consistent with escalc(measure="SMDH", correct=FALSE, vtype="LS2") -> conv.delta(transf=transf.dtocles) + #tmp <- escalc(measure="SMDH", m1i=m1i[i], sd1i=sd1i[i], n1i=n1i[i], m2i=m2i[i], sd2i=sd2i[i], n2i=n2i[i], correct=FALSE, vtype="LS2") + #vi[i] <- conv.delta(yi, vi, data=tmp, transf=transf.dtocles, replace=TRUE)$vi + } + + ### large sample approximation to the sampling variance based on the binormal model (based on standard application of the delta method) + if (vtype[i] == "LS3") { + vi[i] <- exp(-di[i]^2 / 2) / (8*base::pi) * (di[i]^2 * vri[i]^2 / (n1i[i]-1) + di[i]^2 * (1-vri[i])^2 / (n2i[i]-1) + 4*vri[i]/(n1i[i]-0) + 4*(1-vri[i])/(n2i[i]-0)) + # this is consistent with escalc(measure="SMDH", correct=FALSE, vtype="LS3") -> conv.delta(transf=transf.dtocles) + #tmp <- escalc(measure="SMDH", m1i=m1i[i], sd1i=sd1i[i], n1i=n1i[i], m2i=m2i[i], sd2i=sd2i[i], n2i=n2i[i], correct=FALSE, vtype="LS3") + #vi[i] <- conv.delta(yi, vi, data=tmp, transf=transf.dtocles, replace=TRUE)$vi + } + + ### estimate assuming homoscedasticity of the variances within studies + if (vtype[i] == "HO") { + vi[i] <- exp(-di[i]^2 / 2) / (4*base::pi) * (1/n1i[i] + 1/n2i[i] + di[i]^2 / (2*(n1i[i]+n2i[i]))) + # this is consistent with escalc(measure="SMD", correct=FALSE) -> conv.delta(transf=transf.dtocles) + #tmp <- escalc(measure="SMD", m1i=m1i[i], sd1i=sd1i[i], n1i=n1i[i], m2i=m2i[i], sd2i=sd2i[i], n2i=n2i[i], correct=FALSE) + #vi[i] <- conv.delta(yi, vi, data=tmp, transf=transf.dtocles, replace=TRUE)$vi + } + + } + + } + + ###################################################################### + } else { ### in case yi is not NULL (so user wants to convert a regular data frame to an 'escalc' object) @@ -2602,6 +2855,9 @@ data, slab, flip, subset, include, add=1/2, to="only0", drop00=FALSE, vtype="LS" ### add digits attribute attr(dat, "digits") <- digits + ### add vtype attribute + #attr(dat, "vtype") <- vtype + ### add 'yi.names' and 'vi.names' to the first position of the corresponding attributes (so the first is always the last one calculated/added) attr(dat, "yi.names") <- union(var.names[1], attr(data, "yi.names")) # if 'yi.names' is not an attribute, attr() returns NULL, so this works fine attr(dat, "vi.names") <- union(var.names[2], attr(data, "vi.names")) # if 'vi.names' is not an attribute, attr() returns NULL, so this works fine diff --git a/R/misc.func.hidden.r b/R/misc.func.hidden.r index 206a7857..448c95b4 100644 --- a/R/misc.func.hidden.r +++ b/R/misc.func.hidden.r @@ -1192,7 +1192,15 @@ } } ###################################################################### - if (measure == "AUC") { + if (is.element(measure, c("CLES","CLESN"))) { + if (identical(transf.char, "FALSE") && identical(atransf.char, "FALSE")) { + lab <- ifelse(short, "CLES", "Common Language Effect Size") + } else { + lab <- ifelse(short, lab, "Transformed Common Language Effect Size") + } + } + ###################################################################### + if (is.element(measure, c("AUC","AUCN"))) { if (identical(transf.char, "FALSE") && identical(atransf.char, "FALSE")) { lab <- ifelse(short, "AUC", "Area under the Curve") } else { diff --git a/R/rma.glmm.r b/R/rma.glmm.r index a10ff233..a345198b 100644 --- a/R/rma.glmm.r +++ b/R/rma.glmm.r @@ -184,7 +184,7 @@ test="z", level=95, btt, nAGQ=7, verbose=FALSE, digits, control, ...) { di <- .getsubset(di, subset) } - args <- list(measure=measure, ai=ai, bi=bi, ci=ci, di=di, add=add, to=to, drop00=drop00, vtype=vtype, onlyo1=onlyo1, addyi=addyi, addvi=addvi) + args <- list(ai=ai, bi=bi, ci=ci, di=di, add=add, to=to, drop00=drop00, onlyo1=onlyo1, addyi=addyi, addvi=addvi) } @@ -206,7 +206,7 @@ test="z", level=95, btt, nAGQ=7, verbose=FALSE, digits, control, ...) { t2i <- .getsubset(t2i, subset) } - args <- list(measure=measure, x1i=x1i, x2i=x2i, t1i=t1i, t2i=t2i, add=add, to=to, drop00=drop00, vtype=vtype, onlyo1=onlyo1, addyi=addyi, addvi=addvi) + args <- list(x1i=x1i, x2i=x2i, t1i=t1i, t2i=t2i, add=add, to=to, drop00=drop00, onlyo1=onlyo1, addyi=addyi, addvi=addvi) } @@ -227,7 +227,7 @@ test="z", level=95, btt, nAGQ=7, verbose=FALSE, digits, control, ...) { mi <- .getsubset(mi, subset) } - args <- list(measure=measure, xi=xi, mi=mi, add=add, to=to, vtype=vtype, onlyo1=onlyo1, addyi=addyi, addvi=addvi) + args <- list(xi=xi, mi=mi, add=add, to=to, onlyo1=onlyo1, addyi=addyi, addvi=addvi) } @@ -245,10 +245,12 @@ test="z", level=95, btt, nAGQ=7, verbose=FALSE, digits, control, ...) { ti <- .getsubset(ti, subset) } - args <- list(measure=measure, xi=xi, ti=ti, add=add, to=to, vtype=vtype, onlyo1=onlyo1, addyi=addyi, addvi=addvi) + args <- list(xi=xi, ti=ti, add=add, to=to, onlyo1=onlyo1, addyi=addyi, addvi=addvi) } + args <- c(args, list(measure=measure, vtype=vtype)) + dat <- .do.call(escalc, args) yi <- dat$yi # one or more yi/vi pairs may be NA/NA (note: yi/vi pairs that are NA/NA may still have 'valid' table data) diff --git a/R/rma.uni.r b/R/rma.uni.r index df0a843e..b931ec37 100644 --- a/R/rma.uni.r +++ b/R/rma.uni.r @@ -29,7 +29,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { "MN","SMN","MNLN","CVLN","SDLN", # mean, single-group standardized mean, log(mean), log(CV), log(SD), "MC","SMCC","SMCR","SMCRH","SMCRP","SMCRPH","ROMC","CVRC","VRC", # raw/standardized mean change, log(ROM), CVR, and VR for dependent samples "ARAW","AHW","ABT", # alpha (and transformations thereof) - "REH",#"AUC", # relative excess heterozygosity, area under the curve + "REH","CLES","CLESN","AUC","AUCN", # relative excess heterozygosity, common language effect size / area under the curve "HR","HD", # hazard (rate) ratios and differences "GEN"))) stop(mstyle$stop("Unknown 'measure' specified.")) @@ -63,7 +63,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ddd <- list(...) - .chkdots(ddd, c("knha", "onlyo1", "addyi", "addvi", "i2def", "r2def", "skipr2", "abbrev", "dfs", "time", "outlist", "link", "optbeta", "alpha", "beta", "skiphes", "retopt", "pleasedonotreportI2thankyouverymuch")) + .chkdots(ddd, c("knha", "onlyo1", "addyi", "addvi", "correct", "i2def", "r2def", "skipr2", "abbrev", "dfs", "time", "outlist", "link", "optbeta", "alpha", "beta", "skiphes", "retopt", "pleasedonotreportI2thankyouverymuch")) ### handle 'knha' argument from ... (note: overrides test argument) @@ -86,11 +86,12 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { model <- "rma.ls" } - ### set defaults or get onlyo1, addyi, and addvi arguments + ### set defaults or get onlyo1, addyi, addvi, and correct arguments - onlyo1 <- .chkddd(ddd$onlyo1, FALSE) - addyi <- .chkddd(ddd$addyi, TRUE) - addvi <- .chkddd(ddd$addvi, TRUE) + onlyo1 <- .chkddd(ddd$onlyo1, FALSE) + addyi <- .chkddd(ddd$addyi, TRUE) + addvi <- .chkddd(ddd$addvi, TRUE) + correct <- .chkddd(ddd$correct, TRUE) ### set defaults for i2def and r2def @@ -420,7 +421,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { pi <- .getsubset(pi, subset) } - args <- list(measure=measure, ai=ai, bi=bi, ci=ci, di=di, ri=ri, pi=pi, add=add, to=to, drop00=drop00, vtype=vtype, onlyo1=onlyo1, addyi=addyi, addvi=addvi) + args <- list(ai=ai, bi=bi, ci=ci, di=di, ri=ri, pi=pi, add=add, to=to, drop00=drop00, onlyo1=onlyo1, addyi=addyi, addvi=addvi) } @@ -442,7 +443,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { t2i <- .getsubset(t2i, subset) } - args <- list(measure=measure, x1i=x1i, x2i=x2i, t1i=t1i, t2i=t2i, add=add, to=to, drop00=drop00, vtype=vtype, addyi=addyi, addvi=addvi) + args <- list(x1i=x1i, x2i=x2i, t1i=t1i, t2i=t2i, add=add, to=to, drop00=drop00, addyi=addyi, addvi=addvi) } @@ -486,7 +487,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { n2i <- .getsubset(n2i, subset) } - args <- list(measure=measure, m1i=m1i, m2i=m2i, sd1i=sd1i, sd2i=sd2i, n1i=n1i, n2i=n2i, vtype=vtype) + args <- list(m1i=m1i, m2i=m2i, sd1i=sd1i, sd2i=sd2i, n1i=n1i, n2i=n2i) } @@ -512,7 +513,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ni <- .getsubset(ni, subset) } - args <- list(measure=measure, ri=ri, ni=ni, vtype=vtype) + args <- list(ri=ri, ni=ni) } @@ -547,7 +548,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { r2i <- .getsubset(r2i, subset) } - args <- list(measure=measure, ri=ri, mi=mi, ni=ni, r2i=r2i, vtype=vtype) + args <- list(ri=ri, mi=mi, ni=ni, r2i=r2i) } @@ -575,7 +576,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ni <- .getsubset(ni, subset) } - args <- list(measure=measure, r2i=r2i, mi=mi, ni=ni, vtype=vtype) + args <- list(r2i=r2i, mi=mi, ni=ni) } @@ -596,7 +597,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { mi <- .getsubset(mi, subset) } - args <- list(measure=measure, xi=xi, mi=mi, add=add, to=to, vtype=vtype, addyi=addyi, addvi=addvi) + args <- list(xi=xi, mi=mi, add=add, to=to, addyi=addyi, addvi=addvi) } @@ -614,7 +615,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ti <- .getsubset(ti, subset) } - args <- list(measure=measure, xi=xi, ti=ti, add=add, to=to, vtype=vtype, addyi=addyi, addvi=addvi) + args <- list(xi=xi, ti=ti, add=add, to=to, addyi=addyi, addvi=addvi) } @@ -634,7 +635,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ni <- .getsubset(ni, subset) } - args <- list(measure=measure, mi=mi, sdi=sdi, ni=ni, vtype=vtype) + args <- list(mi=mi, sdi=sdi, ni=ni) } @@ -681,7 +682,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ri <- .getsubset(ri, subset) } - args <- list(measure=measure, m1i=m1i, m2i=m2i, sd1i=sd1i, sd2i=sd2i, ri=ri, ni=ni, vtype=vtype) + args <- list(m1i=m1i, m2i=m2i, sd1i=sd1i, sd2i=sd2i, ri=ri, ni=ni) } @@ -701,7 +702,7 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ni <- .getsubset(ni, subset) } - args <- list(measure=measure, ai=ai, mi=mi, ni=ni, vtype=vtype) + args <- list(ai=ai, mi=mi, ni=ni) } @@ -721,15 +722,21 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ci <- .getsubset(ci, subset) } - args <- list(measure=measure, ai=ai, bi=bi, ci=ci, vtype=vtype) + args <- list(ai=ai, bi=bi, ci=ci) } - if (measure == "AUC") { + if (is.element(measure, c("CLES","AUC"))) { ai <- .getx("ai", mf=mf, data=data, checknumeric=TRUE) n1i <- .getx("n1i", mf=mf, data=data, checknumeric=TRUE) n2i <- .getx("n2i", mf=mf, data=data, checknumeric=TRUE) + mi <- .getx("mi", mf=mf, data=data, checknumeric=TRUE) + + if (is.null(mi)) + mi <- rep(0, length(ai)) + + mi[is.na(mi)] <- 0 k <- length(ai) # number of outcomes before subsetting k.all <- k @@ -739,12 +746,79 @@ test="z", level=95, btt, att, tau2, verbose=FALSE, digits, control, ...) { ai <- .getsubset(ai, subset) n1i <- .getsubset(n1i, subset) n2i <- .getsubset(n2i, subset) + mi <- .getsubset(mi, subset) } - args <- list(measure=measure, ai=ai, n1i=n1i, n2i=n2i, vtype=vtype) + args <- list(ai=ai, n1i=n1i, n2i=n2i, mi=mi) } + if (is.element(measure, c("CLESN","AUCN"))) { + + m1i <- .getx("m1i", mf=mf, data=data, checknumeric=TRUE) + m2i <- .getx("m2i", mf=mf, data=data, checknumeric=TRUE) + sd1i <- .getx("sd1i", mf=mf, data=data, checknumeric=TRUE) + sd2i <- .getx("sd2i", mf=mf, data=data, checknumeric=TRUE) + n1i <- .getx("n1i", mf=mf, data=data, checknumeric=TRUE) + n2i <- .getx("n2i", mf=mf, data=data, checknumeric=TRUE) + di <- .getx("di", mf=mf, data=data, checknumeric=TRUE) + ti <- .getx("ti", mf=mf, data=data, checknumeric=TRUE) + pi <- .getx("pi", mf=mf, data=data, checknumeric=TRUE) + ai <- .getx("ai", mf=mf, data=data, checknumeric=TRUE) + + if (!.equal.length(m1i, m2i, sd1i, sd2i, n1i, n2i, di, ti, pi, ai)) + stop(mstyle$stop("Supplied data vectors are not all of the same length.")) + + if (!.all.specified(n1i, n2i)) + stop(mstyle$stop("Cannot compute outcomes. Check that all of the required information is specified\n via the appropriate arguments.")) + + k.all <- max(sapply(list(m1i, m2i, sd1i, sd2i, n1i, n2i, di, ti, pi, ai), length)) + + vtype <- .expand1(vtype, k.all) + + if (is.null(sd1i) || is.null(sd2i)) { + sd1i <- .expand1(NA_real_, k.all) + sd2i <- .expand1(NA_real_, k.all) + } + + ti <- replmiss(ti, .convp2t(pi, df=n1i+n2i-2)) + di <- replmiss(di, ti * sqrt(1/n1i + 1/n2i)) + + if (!is.null(di)) + vtype[!is.na(di)] <- "HO" + + sdpi <- ifelse(vtype=="HO", sqrt(((n1i-1)*sd1i^2 + (n2i-1)*sd2i^2)/(n1i+n2i-2)), sqrt((sd1i^2 + sd2i^2)/2)) + di <- replmiss(di, (m1i - m2i) / sdpi) + + ai <- replmiss(ai, pnorm(di/sqrt(2))) + di <- replmiss(di, qnorm(ai)*sqrt(2)) + + k.all <- length(ai) + + sdsmiss <- is.na(sd1i) | is.na(sd2i) + sd1i <- ifelse(sdsmiss, 1, sd1i) + sd2i <- ifelse(sdsmiss, 1, sd2i) + vtype[sdsmiss] <- "HO" + + k <- length(ai) # number of outcomes before subsetting + k.all <- k + + if (!is.null(subset)) { + subset <- .chksubset(subset, k) + vtype <- .getsubset(vtype, subset) + ai <- .getsubset(ai, subset) + sd1i <- .getsubset(sd1i, subset) + sd2i <- .getsubset(sd2i, subset) + n1i <- .getsubset(n1i, subset) + n2i <- .getsubset(n2i, subset) + } + + args <- list(ai=ai, sd1i=sd1i, sd2i=sd2i, n1i=n1i, n2i=n2i) + + } + + args <- c(args, list(measure=measure, vtype=vtype, correct=correct)) + dat <- .do.call(escalc, args) if (is.element(measure, "GEN")) diff --git a/R/transf.r b/R/transf.r index 3e63d577..69b63eff 100644 --- a/R/transf.r +++ b/R/transf.r @@ -339,7 +339,7 @@ transf.dtorbis <- function(xi, n1i, n2i) { } rpbi <- xi / sqrt(xi^2 + hi) pi <- n1i / (n1i + n2i) - return(sqrt(pi*(1-pi)) / dnorm(pnorm(pi)) * rpbi) + return(sqrt(pi*(1-pi)) / dnorm(qnorm(pi)) * rpbi) } transf.rpbtorbis <- function(xi, pi) { diff --git a/R/zzz.r b/R/zzz.r index 8c8ab38c..0206141b 100644 --- a/R/zzz.r +++ b/R/zzz.r @@ -1,6 +1,6 @@ .onAttach <- function(libname, pkgname) { - ver <- "4.7-34" + ver <- "4.7-35" loadmsg <- paste0("\nLoading the 'metafor' package (version ", ver, "). For an\nintroduction to the package please type: help(metafor)\n") diff --git a/README.md b/README.md index a97ce5f6..ccd8c9af 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ metafor: A Meta-Analysis Package for R [![R build status](https://github.com/wviechtb/metafor/workflows/R-CMD-check/badge.svg)](https://github.com/wviechtb/metafor/actions) [![Code Coverage](https://codecov.io/gh/wviechtb/metafor/branch/master/graph/badge.svg)](https://app.codecov.io/gh/wviechtb/metafor) [![CRAN Version](https://www.r-pkg.org/badges/version/metafor)](https://cran.r-project.org/package=metafor) -[![devel Version](https://img.shields.io/badge/devel-4.7--34-brightgreen.svg)](https://www.metafor-project.org/doku.php/installation#development_version) +[![devel Version](https://img.shields.io/badge/devel-4.7--35-brightgreen.svg)](https://www.metafor-project.org/doku.php/installation#development_version) [![Monthly Downloads](https://cranlogs.r-pkg.org/badges/metafor)](https://cranlogs.r-pkg.org/badges/metafor) [![Total Downloads](https://cranlogs.r-pkg.org/badges/grand-total/metafor)](https://cranlogs.r-pkg.org/badges/grand-total/metafor) diff --git a/docs/404.html b/docs/404.html index 90f392cb..06c13259 100644 --- a/docs/404.html +++ b/docs/404.html @@ -54,7 +54,7 @@
diff --git a/docs/ISSUE_TEMPLATE.html b/docs/ISSUE_TEMPLATE.html index 3b392bf3..a0a2ec24 100644 --- a/docs/ISSUE_TEMPLATE.html +++ b/docs/ISSUE_TEMPLATE.html @@ -29,7 +29,7 @@ diff --git a/docs/articles/index.html b/docs/articles/index.html index 8dbcf29b..b68f9d04 100644 --- a/docs/articles/index.html +++ b/docs/articles/index.html @@ -29,7 +29,7 @@ diff --git a/docs/articles/pkgdown/diagram.html b/docs/articles/pkgdown/diagram.html index 74b7031b..51af9ebe 100644 --- a/docs/articles/pkgdown/diagram.html +++ b/docs/articles/pkgdown/diagram.html @@ -51,7 +51,7 @@ diff --git a/docs/authors.html b/docs/authors.html index 20a7075b..09b0c9a7 100644 --- a/docs/authors.html +++ b/docs/authors.html @@ -29,7 +29,7 @@ diff --git a/docs/index.html b/docs/index.html index b7624373..3f132842 100644 --- a/docs/index.html +++ b/docs/index.html @@ -55,7 +55,7 @@ @@ -121,7 +121,7 @@some general changes to the various forest()
functions: argument header
is now TRUE
by default, the y-axis is now created with yaxs="i"
, and the y-axis limits have been tweaked slightly in accordance
forest.rma()
and the various addpoly()
functions now provides multiple styles for drawing the prediction interval via the predstyle
argument
forest.rma()
and addpoly.rma()
now write out the default label (instead of an abbreviation) for the model results; as before, the label can be changed via the mlab
argument
permutest.rma.uni()
gains a btt
argument and permutest.rma.ls()
gains btt
and att
arguments
selmodel()
gains a subset
argument (to specify a subset of studies to which the selection function should apply)
nobs()
now just returns the number of estimates, not the effective number of observations
added measure "PRZ"
to escalc()
added measures "PRZ"
, "CLES"
, "AUC"
, "CLESN"
, and "AUCN"
to escalc()
escalc()
gains a flip
argument
fixed predict()
ignoring the level
argument for robust.rma
objects obtained with clubSandwich=TRUE
some tweaks were made to vcalc()
to speed up the calculations (by James Pustejovsky)
added transformation function transf.dtoovl()
for transforming standardized mean differences to overlapping coefficient values
added transformation function transf.dtoovl()
(for transforming standardized mean differences to overlapping coefficient values) and `transf.dtocliffd()
(for transforming standardized mean differences to Cliff’s delta values)
escalc()
gains a correct
argument (to specify whether a bias correction should be applied)
better handling of outlist="minimal"
added more tests
a character string to specify which effect size or outcome measure should be calculated. See ‘Details’ for possible options and how the data needed to compute the selected effect size or outcome measure should then be specified (i.e., which of the following arguments need to be used).
a character string to specify which effect size or outcome measure should be calculated (e.g., "SMD"
, "ZCOR"
, "OR"
). See ‘Details’ for possible options and how the data needed to compute the selected effect size or outcome measure should then be specified (i.e., which of the following arguments need to be used).
These arguments pertain to data input:
+ +vector with the \(2 \times 2\) table frequencies (upper left cell).
optional (logical or numeric) vector to specify the subset of studies for which the measure should be calculated. See the ‘Value’ section for more details.
These arguments pertain to handling of zero cells/counts/frequencies:
+ +a non-negative number to specify the amount to add to zero cells, counts, or frequencies. See ‘Details’.
logical to specify whether studies with no cases/events (or only cases) in both groups should be dropped when calculating the observed effect sizes or outcomes. See ‘Details’.
a character string to specify the type of sampling variances to calculate. See ‘Details’.
These arguments pertain to the computations:
+ +a character string to specify the type of sampling variances to calculate. Can also be a vector. See ‘Details’.
logical to specify whether a bias correction should be applied to the effect sizes or outcomes (the default is TRUE
).
These arguments pertain to the formatting of the returned data frame:
+ +character vector with two elements to specify the name of the variable for the observed effect sizes or outcomes and the name of the variable for the corresponding sampling variances (the defaults are "yi"
and "vi"
).
Before a meta-analysis can be conducted, the relevant results from each study must be quantified in such a way that the resulting values can be further aggregated and compared. Depending on (a) the goals of the meta-analysis, (b) the design and types of studies included, and (c) the information provided therein, one of the various effect sizes or outcome measures described below may be appropriate for the meta-analysis and can be computed with the escalc
function.
The measure
argument is a character string to specify the outcome measure that should be calculated (see below for the various options), arguments ai
through ni
are then used to specify the information needed to calculate the various measures (depending on the chosen outcome measure, different arguments need to be specified), and data
can be used to specify a data frame containing the variables given to the previous arguments. The add
, to
, and drop00
arguments may be needed when dealing with frequency or count data that may need special handling when some of the frequencies or counts are equal to zero (see below for details). Finally, the vtype
argument is used to specify how the sampling variances should be estimated (again, see below for details).
The measure
argument is a character string to specify the outcome measure that should be calculated (see below for the various options), arguments ai
through ni
are then used to specify the information needed to calculate the various measures (depending on the chosen outcome measure, different arguments need to be specified), and data
can be used to specify a data frame containing the variables given to the previous arguments. The add
, to
, and drop00
arguments may be needed when dealing with frequency or count data that needs special handling when some of the frequencies or counts are equal to zero (see below for details). Finally, the vtype
argument is used to specify how the sampling variances should be computed (again, see below for details).
To provide a structure to the various effect sizes or outcome measures that can be calculated with the escalc
function, we can distinguish between measures that are used to:
(1) | contrast two independent (either experimentally created or naturally occurring) groups, | |
(2) | describe the direction and strength of the association between two variables, | |
(3) | summarize some characteristic or attribute of individual groups, or | |
(4) | quantify change within a single group or the difference between two matched/paired samples. |
Furthermore, where appropriate, we can further distinguish between measures that are applicable when the characteristic, response, or dependent variable assessed within the individual studies is:
(a) | a quantitative variable (e.g., amount of depression as assessed by a rating scale), | |
(b) | a dichotomous (binary) variable (e.g., remission versus no remission), | |
(c) | a count of events per time unit (e.g., number of migraines per year), or | |
(d) | a mix of the types above. |
Below, these number and letter codes are used (also in combination) to make it easier to quickly find a measure suitable for a particular meta-analysis (e.g., search for (1b)
to find measures that describe the difference between two groups with respect to a dichotomous variable or (2a)
for measures that quantify the association between two quantitative variables).
In many meta-analyses, the goal is to synthesize the results from studies that compare or contrast two groups. The groups may be experimentally defined (e.g., a treatment and a control group created via random assignment) or may occur naturally (e.g., men and women, employees working under high- versus low-stress conditions, people/animals/plants exposed to some environmental risk factor versus those not exposed).
+In many meta-analyses, the goal is to synthesize the results from studies that compare or contrast two groups. The groups may be experimentally defined (e.g., a treatment and a control group created via random assignment) or may occur naturally (e.g., men and women, employees working under high- versus low-stress conditions, people/animals/plants exposed to some environmental risk factor versus those not exposed, patients versus controls).
When the response or dependent variable assessed within the individual studies is measured on a quantitative scale, it is customary to report certain summary statistics, such as the mean and standard deviation of the observations within the two groups (in case medians, min/max values, and quartiles are reported, see conv.fivenum
for a function that can be used to estimate means and standard deviations from such statistics). The data layout for a study comparing two groups with respect to such a variable is then of the form:
mean | standard deviation | group size | ||||
group 1 | m1i | sd1i | n1i | |||
group 2 | m2i | sd2i | n2i |
where m1i
and m2i
are the observed means of the two groups, sd1i
and sd2i
are the observed standard deviations, and n1i
and n2i
denote the number of individuals in each group. The raw mean difference, the standardized mean difference, and the (log transformed) ratio of means (also called the log ‘response ratio’) are useful outcome measures when meta-analyzing studies of this type.
When the response or dependent variable assessed within the individual studies is measured on a quantitative scale, it is customary to report certain summary statistics, such as the mean and standard deviation of the observations within the two groups (in case medians, min/max values, and quartiles are reported, see conv.fivenum
for a function that can be used to estimate means and standard deviations from such statistics). The data layout for a study comparing two groups with respect to such a variable is then of the form:
mean | standard deviation | group size | ||||
group 1 | m1i | sd1i | n1i | |||
group 2 | m2i | sd2i | n2i |
where m1i
and m2i
are the observed means of the two groups, sd1i
and sd2i
are the observed standard deviations, and n1i
and n2i
denote the number of individuals in each group.
Measures for Differences in Central Tendency
+Often, interest is focused on differences between the two groups with respect to their central tendency. The raw mean difference, the standardized mean difference, and the (log transformed) ratio of means (also called the log ‘response ratio’) are useful outcome measures when meta-analyzing studies of this type.
The options for the measure
argument are then:
"MD"
for the raw mean difference (e.g., Borenstein, 2009),
"SMD"
for the standardized mean difference (Hedges, 1981),
"SMD1"
for the standardized mean difference where the mean difference is divided by the standard deviation of the second group (and "SMD1H"
for the same but with heteroscedastic population variances),
"ROM"
for the log transformed ratio of means (Hedges et al., 1999; Lajeunesse, 2011).
The raw mean difference is simply \((\textrm{m1i}-\textrm{m2i})\), while the standardized mean difference is given by \((\textrm{m1i}-\textrm{m2i})/\textrm{sdi}\). For measure="SMD"
, \(\textrm{sdi} = \sqrt{\frac{(\textrm{n1i}-1)\textrm{sd1i}^2 + (\textrm{n2i}-1)\textrm{sd2i}^2}{\textrm{n1i}+\textrm{n2i}-2}}\) is the pooled standard deviation of the two groups (assuming homoscedasticity of the population variances). For measure="SMDH"
, \(\textrm{sdi} = \sqrt{\frac{\textrm{sd1i}^2 + \textrm{sd2i}^2}{2}}\) is the square root of the average variance (allowing for heteroscedastic population variances). Finally, for measure="SMD1"
and measure="SMD1H"
, \(\textrm{sdi} = \textrm{sd2i}\) (note: for measure="SMD1"
, only sd2i
needs to be specified and sd1i
is ignored).
For measure="SMD"
, the positive bias in the standardized mean difference (i.e., in a Cohen's d value) is automatically corrected for within the function, yielding Hedges' g (Hedges, 1981). Similarly, the analogous bias correction is applied for measure="SMDH"
(Bonett, 2009), measure="SMD1"
(Hedges, 1981), and measure="SMD1H"
.
For measure="SMD"
, the positive bias in the standardized mean difference (i.e., in a Cohen's d value) is automatically corrected for within the function, yielding Hedges' g (Hedges, 1981). Similarly, the analogous bias correction is applied for measure="SMDH"
(Bonett, 2009), measure="SMD1"
(Hedges, 1981), and measure="SMD1H"
. With correct=FALSE
, these bias corrections can be switched off.
For measure="ROM"
, the log is taken of the ratio of means (i.e., \(\log(\textrm{m1i}/\textrm{m2i})\)), which makes this outcome measure symmetric around 0 and results in a sampling distribution that is closer to normality. Hence, this measure cannot be computed when m1i
and m2i
have opposite signs (in fact, this measure is only meant to be used for ratio scale measurements, where both means should be positive anyway).
For measure="SMD"
, if the means and standard deviations are unknown for some studies, but the standardized mean differences (Cohen's d values) are directly available (e.g., if they are reported in those studies), then these can be specified via argument di
. Also, if the t-statistics from an independent samples (Student's) t-test are available for some studies, one can specify those values via argument ti
, which are then transformed into the corresponding standardized mean differences within the function (the sign of the t-statistics is then taken to be the sign of the standardized mean differences). If only the (two-sided) p-values corresponding to the t-tests are known, one can specify those values via argument pi
(which are then transformed into the t-statistics and then further into the standardized mean differences). However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the standardized mean difference), the sign of the p-values (which can be negative) is used as the sign of the standardized mean differences (e.g., escalc(measure="SMD", pi=-0.018, n1i=20, n2i=20)
yields a negative standardized mean difference of -0.7664
). See here for a more detailed illustration of using the ti
and pi
arguments.
For measure="MD"
, one can choose between vtype="LS"
(the default) and vtype="HO"
. The former computes the sampling variances without assuming homoscedasticity (i.e., that the true variances of the measurements are the same in group 1 and group 2 within each study), while the latter assumes homoscedasticity (equations 12.5 and 12.3 in Borenstein, 2009, respectively). For measure="SMD"
, one can choose between vtype="LS"
(the default) for the usual large-sample approximation to compute the sampling variances (equation 8 in Hedges, 1982), vtype="LS2"
to compute the sampling variances as described in Borenstein (2009; equation 12.17), vtype="UB"
to compute unbiased estimates of the sampling variances (equation 9 in Hedges, 1983), and vtype="AV"
to compute the sampling variances with the usual large-sample approximation but plugging the sample-size weighted average of the Hedges' g values into the equation. The same choices also apply to measure="SMD1"
. For measure="ROM"
, one can choose between vtype="LS"
(the default) for the usual large-sample approximation to compute the sampling variances (equation 1 in Hedges et al., 1999), vtype="HO"
to compute the sampling variances assuming homoscedasticity (the unnumbered equation after equation 1 in Hedges et al., 1999), vtype="AV"
to compute the sampling variances assuming homoscedasticity of the coefficient of variation within each group across studies, and vtype="AVHO"
to compute the sampling variances assuming homoscedasticity of the coefficient of variation for both groups across studies (see Nakagawa et al., 2023, for details on the latter two options and why they are interesting).
For measure="SMD"
, if the means and standard deviations are unknown for some studies, but the standardized mean differences (Cohen's d values) are directly available (e.g., if they are reported in those studies), then these can be specified via argument di
. Also, if the t-statistics from an independent samples (Student's) t-test are available for some studies, one can specify those values via argument ti
, which are then transformed into the corresponding standardized mean differences within the function (the sign of the t-statistics is then taken to be the sign of the standardized mean differences). If only the two-sided p-values corresponding to the t-tests are known, one can specify those values via argument pi
(which are then transformed into the t-statistics and then further into the standardized mean differences). However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the standardized mean difference), the sign of the p-values (which can be negative) is used as the sign of the standardized mean differences (e.g., escalc(measure="SMD", pi=-0.018, n1i=20, n2i=20)
yields a negative standardized mean difference of -0.7664
). See here for a more detailed illustration of using the ti
and pi
arguments.
For measure="MD"
, one can choose between vtype="LS"
(the default) and vtype="HO"
. The former computes the sampling variances without assuming homoscedasticity (i.e., that the true variances of the measurements are the same in group 1 and group 2 within each study), while the latter assumes homoscedasticity (equations 12.5 and 12.3 in Borenstein, 2009, respectively). For measure="SMD"
, one can choose between vtype="LS"
(the default) for the usual large-sample approximation to compute the sampling variances (equation 8 in Hedges, 1982), vtype="LS2"
to compute the sampling variances as described in Borenstein (2009; equation 12.17), vtype="UB"
to compute unbiased estimates of the sampling variances (equation 9 in Hedges, 1983), and vtype="AV"
to compute the sampling variances with the usual large-sample approximation but plugging the sample-size weighted average of the Hedges' g values into the equation. The same choices also apply to measure="SMD1"
. For measure="ROM"
, one can choose between vtype="LS"
(the default) for the usual large-sample approximation to compute the sampling variances (equation 1 in Hedges et al., 1999), vtype="HO"
to compute the sampling variances assuming homoscedasticity (the unnumbered equation after equation 1 in Hedges et al., 1999), vtype="AV"
to compute the sampling variances assuming homoscedasticity of the coefficient of variation within each group across studies, and vtype="AVHO"
to compute the sampling variances assuming homoscedasticity of the coefficient of variation for both groups across studies (see Nakagawa et al., 2023, for details on the latter two options and why they can be advantageous).
Datasets corresponding to data of this type are provided in dat.normand1999
, dat.curtis1998
, and dat.gibson2002
.
Measures for Variability Differences
Interest may also be focused on differences between the two groups with respect to their variability. Here, the (log transformed) ratio of the coefficient of variation of the two groups (also called the coefficient of variation ratio) can be a useful measure (Nakagawa et al., 2015). If focus is solely on the variability of the measurements within the two groups, then the (log transformed) ratio of the standard deviations (also called the variability ratio) can be used (Nakagawa et al., 2015). For the latter, one only needs to specify sd1i
, sd2i
, n1i
, and n2i
. The options for the measure
argument are:
"CVR"
for the log transformed coefficient of variation ratio,
"VR"
for the log transformed variability ratio.
Measure "CVR"
is computed with \(\log\mathopen{}\left(\left(\textrm{sd1i}/\textrm{m1i}\right) \middle/ \left(\textrm{sd2i}/\textrm{m2i}\right) \right)\mathclose{}\), while "VR"
is simply \(\log(\textrm{sd1i}/\textrm{sd2i})\), but note that a slight bias correction is applied for both of these measures (Nakagawa et al., 2015). Also, the sampling variance for measure="CVR"
is computed as given by equation 12 in Nakagawa et al. (2015), but without the ‘\(-2 \rho \ldots\)’ terms, since for normally distributed data (which we assume here) the mean and variance (and transformations thereof) are independent.
Measure "CVR"
is computed with \(\log\mathopen{}\left(\left(\textrm{sd1i}/\textrm{m1i}\right) \middle/ \left(\textrm{sd2i}/\textrm{m2i}\right) \right)\mathclose{}\), while "VR"
is simply \(\log(\textrm{sd1i}/\textrm{sd2i})\), but note that a slight bias correction is applied for both of these measures (Nakagawa et al., 2015) unless correct=FALSE
. Also, the sampling variances for measure="CVR"
are computed as given by equation 12 in Nakagawa et al. (2015), but without the ‘\(-2 \rho \ldots\)’ terms, since for normally distributed data (which we assume here) the mean and variance (and transformations thereof) are independent.
Measures for Stochastic Superiority
+Another way to quantify the difference between two groups is in terms of the ‘common language effect size’ (CLES) (McGraw & Wong, 1992). This measure provides an estimate of \(P(X > Y)\), that is, the probability that a randomly chosen person from the first group has a larger value on the response variable than a randomly chosen person from the second group (or in case \(X\) and \(Y\) values can be tied, we define the measure as \(P(X > Y) + \frac{1}{2} P(X = Y)\)). This measure is identical to the area under the curve (AUC) under the receiver operating characteristic (ROC) curve (e.g., for a diagnostic test or more broadly for a binary classifier) and the ‘concordance probability’ (or c-statistic) and is directly related to the \(U\) statistic from the Mann-Whitney U test (i.e., \(\textrm{CLES} = U / (n_1 \times n_2)\)).
+If the CLES/AUC values with corresponding sampling variances (or standard errors) are known, they can be directly meta-analyzed for example using the rma.uni
function. However, in practice, one is likely to encounter studies that only report CLES/AUC values and the group sizes. In this case, one can specify these values via the ai
, n1i
, and n2i
arguments and set measure="CLES"
(or equivalently measure="AUC"
). If vtype="LS"
(the default), the sampling variances are then computed based on Newcombe (2006) (method 4), but using (n1i-1)(n2i-1)
in the denominator as suggested by Cho et al. (2019). If vtype="LS2"
, the sampling variances are computed based on Hanley and McNeil (1982; equations 1 and 2), again using (n1i-1)(n2i-1)
in the denominator (and in the unlikely case that the proportion of tied values is known, this can be specified via argument mi
, in which case the adjustment as described by Cho et al. (2019) is also applied).
Under the assumption that the data within the two groups are normally distributed (the so-called binormal model), one can also estimate the CLES/AUC values from the means and standard deviations of the two groups. For this, one sets measure="CLESN"
(or equivalently measure="AUCN"
) and specifies the means via arguments m1i
and m2i
, the standard deviations via arguments sd1i
and sd2i
, and the group sizes via arguments n1i
and n2i
. If vtype="LS"
(the default), the sampling variances are then computed based on the large-sample approximation derived via the delta method (equation 3 (with a correction, since the plus sign in front of last term in braces should be a multiplication sign) and equation 4 in Goddard & Hinberg, 1990, but using n1i-1
and n2i-1
in the denominators). Computing the CLES/AUC values and corresponding sampling variances does not assume homoscedasticity of the variances in the two groups. However, when vtype="HO"
, then homoscedasticity is assumed (this will also affect the calculation of the CLES/AUC values themselves). As for measure="SMD"
, one can also specify standardized mean differences via argument di
, t-statistics from an independent samples t-test via argument ti
, and/or signed two-sided p-values corresponding to the t-tests via argument pi
, which all can be converted into CLES/AUC values (note that this automatically assumes homoscedasticity). One can also directly specify binormal model CLES/AUC values via argument ai
(but unless the corresponding sd1i
and sd2i
values are also specified, the sampling variances are then computed under the assumption of homoscedasticity).
"COR"
for the raw correlation coefficient,
"UCOR"
for the raw correlation coefficient corrected for its slight negative bias (based on equation 2.3 in Olkin & Pratt, 1958),
"ZCOR"
for Fisher's r-to-z transformed correlation coefficient (Fisher, 1921).
If the correlation coefficient is unknown for some studies, but the t-statistics (i.e., \(t_i = r_i \sqrt{n_i - 2} / \sqrt{1 - r_i^2}\)) are available for those studies (for the standard test of \(\text{H}_0{:}\; \rho_i = 0\)), one can specify those values via argument ti
, which are then transformed into the corresponding correlation coefficients within the function (the sign of the t-statistics is then taken to be the sign of the correlations). If only the (two-sided) p-values corresponding to the t-tests are known, one can specify those values via argument pi
. However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the correlation), the sign of the p-values (which can be negative) is used as the sign of the correlation coefficients (e.g., escalc(measure="COR", pi=-0.07, ni=30)
yields a negative correlation of -0.3354
).
If the correlation coefficient is unknown for some studies, but the t-statistics (i.e., \(t_i = r_i \sqrt{n_i - 2} / \sqrt{1 - r_i^2}\)) are available for those studies (for the standard test of \(\text{H}_0{:}\; \rho_i = 0\)), one can specify those values via argument ti
, which are then transformed into the corresponding correlation coefficients within the function (the sign of the t-statistics is then taken to be the sign of the correlations). If only the two-sided p-values corresponding to the t-tests are known, one can specify those values via argument pi
. However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the correlation), the sign of the p-values (which can be negative) is used as the sign of the correlation coefficients (e.g., escalc(measure="COR", pi=-0.07, ni=30)
yields a negative correlation of -0.3354
).
For measure="COR"
and measure="UCOR"
, one can choose between vtype="LS"
(the default) for the usual large-sample approximation to compute the sampling variances (i.e., plugging the (biased-corrected) correlation coefficients into equation 12.27 in Borenstein, 2009) and vtype="AV"
to compute the sampling variances with the usual large-sample approximation but plugging the sample-size weighted average of the (bias-corrected) correlation coefficients into the equation. For measure="UCOR"
, one can also choose vtype="UB"
to compute unbiased estimates of the sampling variances (see Hedges, 1989, but using the exact equation instead of the approximation).
Datasets corresponding to data of this type are provided in dat.mcdaniel1994
and dat.molloy2014
.
For meta-analyses involving multiple (dependent) correlation coefficients extracted from the same sample, see also the rcalc
function.
"RPB"
for the point-biserial correlation coefficient,
"RBIS"
for the biserial correlation coefficient.
There are also measures "ZPB"
and "ZBIS"
for applying Fisher's r-to-z transformation to these measures. This may be useful when combining these with other types of correlation coefficients that were r-to-z transformed. However, note that the r-to-z transformation is not a variance-stabilizing transformation for these measures.
If the means and standard deviations are unknown for some studies, one can also use arguments di
, ti
, or pi
to specify standardized mean differences (Cohen's d values), t-statistics from an independent samples t-test, or (signed) p-values for the t-test, respectively, as described earlier under (1a) (together with the group sizes, these are sufficient statistics for computing the (point-)biserial correlation coefficients).
If the means and standard deviations are unknown for some studies, one can also use arguments di
, ti
, or pi
to specify standardized mean differences (Cohen's d values), t-statistics from an independent samples t-test, or signed p-values for the t-test, respectively, as described earlier under (1a) (together with the group sizes, these are sufficient statistics for computing the (point-)biserial correlation coefficients).
For measure="RPB"
, one must indicate via vtype="ST"
or vtype="CS"
whether the data for the studies were obtained using stratified or cross-sectional (i.e., multinomial) sampling, respectively (it is also possible to specify an entire vector for the vtype
argument in case the sampling scheme differed for the various studies).
"MNLN"
for the log transformed mean,
"CVLN"
for the log transformed coefficient of variation,
"SDLN"
for the log transformed standard deviation.
Note that sdi
is used to specify the standard deviations of the observed values of the response, characteristic, or dependent variable and not the standard errors of the means. Also, the sampling variance for measure="CVLN"
is computed as given by equation 27 in Nakagawa et al. (2015), but without the ‘\(-2 \rho \ldots\)’ term, since for normally distributed data (which we assume here) the mean and variance (and transformations thereof) are independent.
Note that sdi
is used to specify the standard deviations of the observed values of the response, characteristic, or dependent variable and not the standard errors of the means. Also, the sampling variances for measure="CVLN"
are computed as given by equation 27 in Nakagawa et al. (2015), but without the ‘\(-2 \rho \ldots\)’ term, since for normally distributed data (which we assume here) the mean and variance (and transformations thereof) are independent.
"SMCRPH"
for the standardized mean change using raw score standardization with pooled standard deviations and heteroscedastic population variances at the two measurement occasions (Bonett, 2008),
"ROMC"
for the log transformed ratio of means (Lajeunesse, 2011).
The raw mean change is simply \(\textrm{m1i}-\textrm{m2i}\), while the standardized mean change is given by \((\textrm{m1i}-\textrm{m2i})/\textrm{sdi}\). For measure="SMCC"
, \(\textrm{sdi} = \sqrt{\textrm{sd1i}^2 + \textrm{sd2i}^2 - 2\times\textrm{ri}\times\textrm{sd1i}\times\textrm{sd2i}}\) is the standard deviation of the change scores, for measure="SMCR"
and measure="SMCRH"
, \(\textrm{sdi} = \textrm{sd1i}\), and for measure="SMCRP"
and measure="SMCRPH"
, \(\textrm{sdi} = \sqrt{\frac{\textrm{sd1i}^2 + \textrm{sd2i}^2}{2}}\) is the square root of the average variance. See also Morris and DeShon (2002) for a thorough discussion of the difference between the "SMCC"
and "SMCR"
change score measures. All of these measures are also applicable for matched pairs designs (subscripts 1 and 2 then simply denote the first and second group that are formed by the matching).
In practice, one often has a mix of information available from the individual studies to compute these measures. In particular, if m1i
and m2i
are unknown, but the raw mean change is directly reported in a particular study, then one can set m1i
to that value and m2i
to 0 (making sure that the raw mean change was computed as m1i-m2i
within that study and not the other way around). Also, for measures "MC"
and "SMCC"
, if sd1i
, sd2i
, and ri
are unknown, but the standard deviation of the change scores is directly reported, then one can set sd1i
to that value and both sd2i
and ri
to 0. For measure "SMCR"
, argument sd2i
is actually not needed, as the standardization is only based on sd1i
(Becker, 1988; Morris, 2000), which is usually the pre-test standard deviation (if the post-test standard deviation should be used, then set sd1i
to that). Finally, for measure="SMCC"
, one can also directly specify standardized mean change values via argument di
or the t-statistics from a paired samples t-test or the corresponding (two-sided) p-values via argument ti
or pi
, respectively (which are then transformed into the corresponding standardized mean change values within the function). The sign of the p-values (which can be negative) is used as the sign of the standardized mean change values (e.g., escalc(measure="SMCC", pi=-0.018, ni=50)
yields a negative standardized mean change value of -0.3408
).
In practice, one often has a mix of information available from the individual studies to compute these measures. In particular, if m1i
and m2i
are unknown, but the raw mean change is directly reported in a particular study, then one can set m1i
to that value and m2i
to 0 (making sure that the raw mean change was computed as m1i-m2i
within that study and not the other way around). Also, for measures "MC"
and "SMCC"
, if sd1i
, sd2i
, and ri
are unknown, but the standard deviation of the change scores is directly reported, then one can set sd1i
to that value and both sd2i
and ri
to 0. For measure "SMCR"
, argument sd2i
is actually not needed, as the standardization is only based on sd1i
(Becker, 1988; Morris, 2000), which is usually the pre-test standard deviation (if the post-test standard deviation should be used, then set sd1i
to that). Finally, for measure="SMCC"
, one can also directly specify standardized mean change values via argument di
or the t-statistics from a paired samples t-test or the corresponding two-sided p-values via argument ti
or pi
, respectively (which are then transformed into the corresponding standardized mean change values within the function). The sign of the p-values (which can be negative) is used as the sign of the standardized mean change values (e.g., escalc(measure="SMCC", pi=-0.018, ni=50)
yields a negative standardized mean change value of -0.3408
).
Finally, interest may also be focused on differences in the variability of the measurements at the two measurement occasions (or between the two matched groups). Here, the (log transformed) ratio of the coefficient of variation (also called the coefficient of variation ratio) can be a useful measure (Nakagawa et al., 2015). If focus is solely on the variability of the measurements, then the (log transformed) ratio of the standard deviations (also called the variability ratio) can be used (Nakagawa et al., 2015). For the latter, one only needs to specify sd1i
, sd2i
, ni
, and ri
. The options for the measure
argument are:
"CVRC"
for the log transformed coefficient of variation ratio,
"VRC"
for the log transformed variability ratio.
"MPORC"
for the conditional log odds ratio,
"MPPETO"
for the conditional log odds ratio estimated with Peto's method.
See Curtin et al. (2002) and Zou (2007) for discussions of these measures.
-If only marginal tables are available, then another possibility is to compute the marginal log odds ratios based on these table directly. However, for the correct computation of the sampling variances, the correlations (phi coefficients) from the paired tables must be known (or ‘guestimated’). To use this approach, set measure="MPORM"
and use argument ri
to specify the correlation coefficients. Instead of specifying ri
, one can use argument pi
to specify the proportions (or ‘guestimates’ thereof) of individuals (or pairs) that experienced the outcome of interest (i.e., ‘outcome1’ in the paired \(2 \times 2\) table) under both treatments (i.e., pi=ai/(ai+bi+ci+di)
). Based on these proportions, the correlation coefficients are then back-calculated and used to calculate the correct sampling variances. Note that the values in the marginal tables put constraints on the possible values for ri
and pi
. If a specified value for ri
or pi
is not feasible under a given table, the corresponding sampling variance will be NA
.
If only marginal tables are available, then another possibility is to compute the marginal log odds ratios based on these table directly. However, for the correct computation of the sampling variances, the correlations (phi coefficients) from the paired tables must be known (or ‘guestimated’). To use this approach, set measure="MPORM"
and use argument ri
to specify the correlation coefficients. Instead of specifying ri
, one can use argument pi
to specify the proportions (or ‘guestimates’ thereof) of individuals (or pairs) that experienced the outcome of interest (i.e., ‘outcome1’ in the paired \(2 \times 2\) table) under both treatments (i.e., pi=ai/(ai+bi+ci+di)
). Based on these proportions, the correlation coefficients are then back-calculated and used to compute the correct sampling variances. Note that the values in the marginal tables put constraints on the possible values for ri
and pi
. If a specified value for ri
or pi
is not feasible under a given table, the corresponding sampling variance will be NA
.
"SPCOR"
for the semi-partial correlation coefficient,
"ZSPCOR"
for Fisher's r-to-z transformed semi-partial correlation coefficient.
Note that the signs of the (semi-)partial correlation coefficients is determined based on the signs of the values specified via the ti
argument. Also, while the Fisher transformation can be applied to both measures, it is only a variance-stabilizing transformation for partial correlation coefficients.
If the test statistic (i.e., t-test) of the regression coefficient of interest is unknown for some studies, but the (two-sided) p-values corresponding to the t-tests are known, one can specify those values via argument pi
. However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the correlation), the sign of the p-values (which can be negative) is used as the sign of the correlation coefficients (e.g., escalc(measure="PCOR", pi=-0.07, mi=5, ni=30)
yields a negative partial correlation of -0.3610
).
If the test statistic (i.e., t-test) of the regression coefficient of interest is unknown for some studies, but the two-sided p-values corresponding to the t-tests are known, one can specify those values via argument pi
. However, since a two-sided p-value does not carry information about the sign of the test statistic (and hence neither about the correlation), the sign of the p-values (which can be negative) is used as the sign of the correlation coefficients (e.g., escalc(measure="PCOR", pi=-0.07, mi=5, ni=30)
yields a negative partial correlation of -0.3610
).
In the rare case that the (semi-)partial correlations are known for some of the studies, then these can be directly specified via the ri
argument. This can be useful, for example, when \(\eta^2_p\) (i.e., partial eta squared) is known for the regression coefficient of interest, since the square root thereof is identical to the absolute value of the partial correlation (although the correct sign then still needs to be reconstructed based on other information).
A dataset corresponding to data of this type is provided in dat.aloe2013
.
Bonett, D. G. (2010). Varying coefficient meta-analytic methods for alpha reliability. Psychological Methods, 15(4), 368–385. https://doi.org/10.1037/a0020142
Borenstein, M. (2009). Effect sizes for continuous data. In H. Cooper, L. V. Hedges, & J. C. Valentine (Eds.), The handbook of research synthesis and meta-analysis (2nd ed., pp. 221–235). New York: Russell Sage Foundation.
Chinn, S. (2000). A simple method for converting an odds ratio to effect size for use in meta-analysis. Statistics in Medicine, 19(22), 3127–3131. https://doi.org/10.1002/1097-0258(20001130)19:22<3127::aid-sim784>3.0.co;2-m
+Cho, H., Matthews, G. J., & Harel, O. (2019). Confidence intervals for the area under the receiver operating characteristic curve in the presence of ignorable missing data. International Statistical Review, 87(1), 152–177. https://doi.org/10.1111/insr.12277
Cohen, J. (1988). Statistical power analysis for the behavioral sciences (2nd ed.). Hillsdale, NJ: Lawrence Erlbaum Associates.
Cousineau, D. (2020). Approximating the distribution of Cohen's d_p in within-subject designs. The Quantitative Methods for Psychology, 16(4), 418–421. https://doi.org/10.20982/tqmp.16.4.p418
Cox, D. R., & Snell, E. J. (1989). Analysis of binary data (2nd ed.). London: Chapman & Hall.
@@ -613,7 +637,9 @@Fleiss, J. L., & Berlin, J. (2009). Effect sizes for dichotomous data. In H. Cooper, L. V. Hedges, & J. C. Valentine (Eds.), The handbook of research synthesis and meta-analysis (2nd ed., pp. 237–253). New York: Russell Sage Foundation.
Freeman, M. F., & Tukey, J. W. (1950). Transformations related to the angular and the square root. Annals of Mathematical Statistics, 21(4), 607–611. https://doi.org/10.1214/aoms/1177729756
Gibbons, R. D., Hedeker, D. R., & Davis, J. M. (1993). Estimation of effect size from a series of experiments involving paired comparisons. Journal of Educational Statistics, 18(3), 271–279. https://doi.org/10.3102/10769986018003271
+Goddard, M. J., & Hinberg, I. (1990). Receiver operator characteristic (ROC) curves and non‐normal data: An empirical study. Statistics in Medicine, 9(3), 325–337. https://doi.org/10.1002/sim.4780090315
Hakstian, A. R., & Whalen, T. E. (1976). A k-sample significance test for independent alpha coefficients. Psychometrika, 41(2), 219–231. https://doi.org/10.1007/BF02291840
+Hanley, J. A., & McNeil, B. J. (1982). The meaning and use of the area under a receiver operating characteristic (ROC) curve. Radiology, 143(1), 29–36. https://doi.org/10.1148/radiology.143.1.7063747
Hasselblad, V., & Hedges, L. V. (1995). Meta-analysis of screening and diagnostic tests. Psychological Bulletin, 117(1), 167–178. https://doi.org/10.1037/0033-2909.117.1.167
Hedges, L. V. (1981). Distribution theory for Glass's estimator of effect size and related estimators. Journal of Educational Statistics, 6(2), 107–128. https://doi.org/10.3102/10769986006002107
Hedges, L. V. (1982). Estimation of effect size from a series of independent experiments. Psychological Bulletin, 92(2), 490–499. https://doi.org/10.1037/0033-2909.92.2.490
@@ -626,11 +652,13 @@Kirk, D. B. (1973). On the numerical approximation of the bivariate normal (tetrachoric) correlation coefficient. Psychometrika, 38(2), 259–268. https://doi.org/10.1007/BF02291118
Lajeunesse, M. J. (2011). On the meta-analysis of response ratios for studies with correlated and multi-group designs. Ecology, 92(11), 2049–2055. https://doi.org/10.1890/11-0423.1
May, W. L., & Johnson, W. D. (1997). Confidence intervals for differences in correlated binary proportions. Statistics in Medicine, 16(18), 2127–2136. https://doi.org/10.1002/(SICI)1097-0258(19970930)16:18<2127::AID-SIM633>3.0.CO;2-W
+McGraw, K. O., & Wong, S. P. (1992). A common language effect size statistic. Psychological Bulletin, 111(2), 361–365. https://doi.org/10.1037/0033-2909.111.2.361
Morris, S. B. (2000). Distribution of the standardized mean change effect size for meta-analysis on repeated measures. British Journal of Mathematical and Statistical Psychology, 53(1), 17–29. https://doi.org/10.1348/000711000159150
Morris, S. B., & DeShon, R. P. (2002). Combining effect size estimates in meta-analysis with repeated measures and independent-groups designs. Psychological Methods, 7(1), 105–125. https://doi.org/10.1037/1082-989x.7.1.105
Nakagawa, S., Poulin, R., Mengersen, K., Reinhold, K., Engqvist, L., Lagisz, M., & Senior, A. M. (2015). Meta-analysis of variation: Ecological and evolutionary applications and beyond. Methods in Ecology and Evolution, 6(2), 143–152. https://doi.org/10.1111/2041-210x.12309
Nakagawa, S., Noble, D. W. A., Lagisz, M., Spake, R., Viechtbauer, W., & Senior, A. M. (2023). A robust and readily implementable method for the meta-analysis of response ratios with and without missing standard deviations. Ecology Letters, 26(2), 232–244. https://doi.org/10.1111/ele.14144
Newcombe, R. G. (1998). Improved confidence intervals for the difference between binomial proportions based on paired data. Statistics in Medicine, 17(22), 2635–2650. https://doi.org/10.1002/(SICI)1097-0258(19981130)17:22<2635::AID-SIM954>3.0.CO;2-C
+Newcombe, R. G. (2006). Confidence intervals for an effect size measure based on the Mann-Whitney statistic. Part 2: Asymptotic methods and evaluation. Statistics in Medicine, 25(4), 559–573. https://doi.org/10.1002/sim.2324
Olkin, I., & Finn, J. D. (1995). Correlations redux. Psychological Bulletin, 118(1), 155–164. https://doi.org/10.1037/0033-2909.118.1.155
Olkin, I., & Pratt, J. W. (1958). Unbiased estimation of certain correlation coefficients. Annals of Mathematical Statistics, 29(1), 201–211. https://doi.org/10.1214/aoms/1177706717
Pearson, K. (1900). Mathematical contributions to the theory of evolution. VII. On the correlation of characters not quantitatively measurable. Philosophical Transactions of the Royal Society of London, Series A, 195, 1–47. https://doi.org/10.1098/rsta.1900.0022
diff --git a/docs/reference/fitstats.html b/docs/reference/fitstats.html index 77b9a34a..c84996a9 100644 --- a/docs/reference/fitstats.html +++ b/docs/reference/fitstats.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/fitted.rma.html b/docs/reference/fitted.rma.html index 8d31cf0e..c844d57d 100644 --- a/docs/reference/fitted.rma.html +++ b/docs/reference/fitted.rma.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/forest.cumul.rma.html b/docs/reference/forest.cumul.rma.html index ce5cb7f1..acc617cd 100644 --- a/docs/reference/forest.cumul.rma.html +++ b/docs/reference/forest.cumul.rma.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/forest.default.html b/docs/reference/forest.default.html index e54abde4..e24176a2 100644 --- a/docs/reference/forest.default.html +++ b/docs/reference/forest.default.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/forest.html b/docs/reference/forest.html index 96e27a01..4dce5a27 100644 --- a/docs/reference/forest.html +++ b/docs/reference/forest.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/forest.rma.html b/docs/reference/forest.rma.html index 9a88c078..1e9dc349 100644 --- a/docs/reference/forest.rma.html +++ b/docs/reference/forest.rma.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/formatters.html b/docs/reference/formatters.html index c51dc33d..deb4ee9e 100644 --- a/docs/reference/formatters.html +++ b/docs/reference/formatters.html @@ -29,7 +29,7 @@ diff --git a/docs/reference/formula.rma.html b/docs/reference/formula.rma.html index 26be18fe..56da69ae 100644 --- a/docs/reference/formula.rma.html +++ b/docs/reference/formula.rma.html @@ -29,7 +29,7 @@ @@ -142,13 +142,13 @@transf.ztor()
transf.logit()
transf.ilogit()
transf.arcsin()
transf.iarcsin()
transf.pft()
transf.ipft()
transf.ipft.hm()
transf.isqrt()
transf.irft()
transf.iirft()
transf.ahw()
transf.iahw()
transf.abt()
transf.iabt()
transf.r2toz()
transf.ztor2()
transf.ztor.int()
transf.exp.int()
transf.ilogit.int()
transf.dtou1()
transf.dtou2()
transf.dtou3()
transf.dtoovl()
transf.dtocles()
transf.dtobesd()
transf.dtomd()
transf.dtorpb()
transf.dtorbis()
transf.rpbtorbis()
transf.rtorpb()
transf.rtod()
transf.rpbtod()
transf.lnortord()
transf.lnortorr()
transf.lnortod.norm()
transf.lnortod.logis()
transf.dtolnor.norm()
transf.dtolnor.logis()
transf.lnortortet.pearson()
transf.lnortortet.digby()
+ transf.rtoz()
transf.ztor()
transf.logit()
transf.ilogit()
transf.arcsin()
transf.iarcsin()
transf.pft()
transf.ipft()
transf.ipft.hm()
transf.isqrt()
transf.irft()
transf.iirft()
transf.ahw()
transf.iahw()
transf.abt()
transf.iabt()
transf.r2toz()
transf.ztor2()
transf.ztor.int()
transf.exp.int()
transf.ilogit.int()
transf.dtou1()
transf.dtou2()
transf.dtou3()
transf.dtoovl()
transf.dtocles()
transf.dtocliffd()
transf.dtobesd()
transf.dtomd()
transf.dtorpb()
transf.dtorbis()
transf.rpbtorbis()
transf.rtorpb()
transf.rtod()
transf.rpbtod()
transf.lnortord()
transf.lnortorr()
transf.lnortod.norm()
transf.lnortod.logis()
transf.dtolnor.norm()
transf.dtolnor.logis()
transf.lnortortet.pearson()
transf.lnortortet.digby()
Transformation Functions