You often already have a continuous meta-analysis fitted and saved in an R object. respondeR can read that object directly and express it as responder risks, so you do not have to rebuild the arm-level data frame by hand. It reads the saved object with base R, so the package that produced it (for example meta or metafor) does not even need to be attached.
There are two situations, handled automatically:
metacont from meta): it is converted to the
data-frame form and analyzed with the full method menu;rma fit): it is converted with
responder_from_effect(), and you supply a baseline control
responder risk (by name: baseline =).meta (metacont) objectA metacont object stores both arms, so respondeR can run
the complete analysis. You would normally create it like this:
library(meta)
fit <- metacont(
n.e = n_e, mean.e = change_e, sd.e = sd_e,
n.c = n_c, mean.c = change_c, sd.c = sd_c,
studlab = study, data = sample_responder_data
)
responder_analysis(fit, mid = 1)A metacont object is, in the end, a list with the
per-arm fields respondeR reads (mean.e, sd.e,
n.e, mean.c, sd.c,
n.c, studlab). To keep this vignette runnable
without meta installed, here is the same object built by
hand:
d <- sample_responder_data
fit_meta <- structure(
list(
studlab = d$study,
n.e = d$n_e, mean.e = d$change_e, sd.e = d$sd_e,
n.c = d$n_c, mean.c = d$change_c, sd.c = d$sd_c,
sm = "MD"
),
class = c("metacont", "meta")
)
responder_analysis(fit_meta, mid = 1)[, c("method", "p_e", "p_c", "rd", "rr", "or")]
#> method p_e p_c rd rr or
#> 1 individual NA NA 0.2548985 2.148360 3.197922
#> 2 weighted 0.4757294 0.2205372 0.2551921 2.157138 3.207140
#> 3 unweighted 0.4767051 0.2279613 0.2487438 2.091167 3.085185
#> 4 median 0.4869694 0.2150781 0.2718912 2.264151 3.464085That is identical to calling responder_analysis() on the
data frame; all the usual arguments (direction,
method, pooling, control, …) pass
straight through. The fitted object’s own choices carry over unless you
override them: studies excluded from the fit (its exclude
argument) are dropped, a random-effects fit
(common = FALSE, random = TRUE) sets
pooling = "random", its method.tau (DL or
REML) sets tau_method, and a Hartung-Knapp fit sets
ci_method = "hksj". Repeated study labels (the comparisons
of a multi-arm trial) become a trial column, so a shared
control arm is split rather than double counted. If you only want the
extracted data frame, use as_responder_data().
metafor rma objectAn rma fit keeps the pooled relative effect, not the
arms. respondeR reads the estimate, its standard error, its confidence
interval (so a Knapp-Hartung t interval and the fit’s
confidence level are kept) and the effect measure, then converts.
Because the arms are gone, you must tell it the
baseline control responder risk (as a probability, or
as a control mean and SD), by name. Meta-regressions, models without an
intercept and raw-mean measures are rejected.
library(metafor)
#> Warning: package 'metafor' was built under R version 4.6.1
#> Loading required package: Matrix
#> Warning: package 'Matrix' was built under R version 4.6.1
#> Loading required package: metadat
#> Loading required package: numDeriv
#>
#> Loading the 'metafor' package (version 5.2-1). For an
#> introduction to the package please type: help(metafor)
es <- escalc(
measure = "SMD", m1i = change_e, sd1i = sd_e, n1i = n_e,
m2i = change_c, sd2i = sd_c, n2i = n_c, data = d
)
fit_rma <- rma(yi, vi, data = es)
# A standardized mean difference, against a 22% control responder rate:
responder_analysis(fit_rma, baseline = 0.22)[, c("method", "p_e", "p_c", "rd", "or")]
#> method p_e p_c rd or
#> 1 metafor 0.4994262 0.22 0.2794262 3.537327The effect is read as experimental minus control and oriented by
direction. For pain, where a reduction is the response, a
negative SMD is a benefit:
es_vas <- escalc(
measure = "SMD", m1i = change_e, sd1i = sd_e, n1i = n_e,
m2i = change_c, sd2i = sd_c, n2i = n_c, data = vas_pain
)
fit_vas <- rma(yi, vi, data = es_vas, test = "knha")
responder_analysis(fit_vas, baseline = 0.4, direction = "lower")
#> Responder analysis (respondeR)
#> Percentages; 95% confidence intervals.
#>
#> Method PE PC RD RR OR
#> metafor 76.3 40.0 36.3 (27.3 to 43.5) 1.91 (1.68 to 2.09) 4.84 (3.09 to 7.57)
#> NNT
#> NNTB 2.8 (2.3 to 3.7)
#>
#> Use as.data.frame() for every column, summary() for details, plot() for a forest plot.For a mean-difference model you also pass a reference within-arm SD
(sd_ref), the scale on which the threshold lives, and you
can give the baseline as a control mean and SD:
es_md <- escalc(
measure = "MD", m1i = change_e, sd1i = sd_e, n1i = n_e,
m2i = change_c, sd2i = sd_c, n2i = n_c, data = d
)
fit_md <- rma(yi, vi, data = es_md)
responder_analysis(fit_md, baseline = list(mean = 0, sd = 1.3),
mid = 1, sd_ref = 1.3)[, c("method", "p_e", "p_c", "rd")]
#> method p_e p_c rd
#> 1 metafor 0.4696273 0.2208782 0.2487491If all you have is a number from a paper (a pooled SMD or MD with its SE), call the engine directly:
For a standardized mean difference g,
respondeR maps it to an odds ratio through the logistic distribution,
lnOR = (pi / sqrt(3)) g (Hasselblad and Hedges, 1995;
Chinn, 2000; Anzures-Cabrera, Sarpatwari & Higgins, 2011), then
combines that odds ratio with the control responder proportion
p_c to recover the experimental proportion and the risk
difference, risk ratio, odds ratio and NNT.
For a mean difference MD, respondeR
shifts the control responder probability along the Normal cut-point:
p_e = Phi(Phi^-1(p_c) + MD / sigma), where
sigma is the reference within-arm SD (sd_ref).
This conversion assumes Normal change scores. Both risks depend on the
same baseline, so when the baseline is estimated (a mean, SD and
n) its uncertainty is propagated jointly with that of the
effect.
Two assumptions matter. First, the baseline is yours to choose: a defensible control responder rate, taken from a representative control arm or an external source, much as a GRADE summary-of-findings table fixes one baseline risk. A fixed baseline probability gives intervals conditional on it. Second, the mean-difference path needs a reference SD; pick the typical within-arm SD on the outcome scale, and report it.
Support for network meta-analysis objects (netmeta) and
Bayesian network meta-analysis / multilevel network meta-regression
(multinma) is planned for a later release: each comparison
or posterior draw will be converted to responder risks against a chosen
baseline.
Thorlund, K., Walter, S. D., Johnston, B. C., Furukawa, T. A., & Guyatt, G. H. (2011). Pooling health-related quality of life outcomes in meta-analysis. Research Synthesis Methods, 2(3), 188 to 203. doi:10.1002/jrsm.46
Anzures-Cabrera, J., Sarpatwari, A., & Higgins, J. P. T. (2011). Expressing findings from meta-analyses of continuous outcomes in terms of risks. Statistics in Medicine, 30(25), 2967 to 2985. doi:10.1002/sim.4298
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 to 3131.
Hasselblad, V., & Hedges, L. V. (1995). Meta-analysis of screening and diagnostic tests. Psychological Bulletin, 117(1), 167 to 178.