| Title: | Imputing Responder Proportions from Continuous Outcomes |
|---|---|
| Description: | Express meta-analyses of continuous trial outcomes in terms of responder risks, following the interpretability tutorial of Thorlund, Walter, Johnston, Furukawa and Guyatt (2011) <doi:10.1002/jrsm.46>. Given the mean change, standard deviation and sample size per arm across studies, respondeR estimates the proportion of patients who cross a minimal important difference (MID) threshold under a parametric model for the change scores, and contrasts the arms as a risk difference, risk ratio, odds ratio or number needed to treat. It provides median, unweighted-mean, weighted-mean and per-study (fixed- or random-effects) pooling, the standardized-mean-difference to odds-ratio bridge of Anzures-Cabrera, Sarpatwari and Higgins (2011) <doi:10.1002/sim.4298>, a threshold-free common-language effect size, and a point-and-click 'Shiny' application. The estimation methods were evaluated in a simulation study by Sofi-Mahmudi (2024) <https://hdl.handle.net/11375/30210>. |
| Authors: | Ahmad Sofi-Mahmudi [aut, cre] (ORCID: <https://orcid.org/0000-0001-6829-0823>) |
| Maintainer: | Ahmad Sofi-Mahmudi <[email protected]> |
| License: | GPL-3 |
| Version: | 0.1.0 |
| Built: | 2026-06-19 16:43:59 UTC |
| Source: | https://github.com/cran/respondeR |
Turns the numeric output of responder_analysis() into a compact,
display-ready data frame: proportions and risk differences as percentages,
the risk ratio and odds ratio with intervals, and a combined "RD (CI)"
string. Used by the bundled Shiny app and handy for reports.
format_responder_results(results, digits = 1)format_responder_results(results, digits = 1)
results |
A data frame returned by |
digits |
Number of decimal places (default |
A data frame with character columns Method, PE, PC, RD, RR
and OR (percentages for proportions/RD; ratios for RR/OR). Methods
without a variance model show point estimates only.
format_responder_results(responder_analysis(sample_responder_data, mid = 1))format_responder_results(responder_analysis(sample_responder_data, mid = 1))
Starts the bundled Shiny application, a point-and-click front end to
responder_analysis(): upload data (or load the example), set the MID and
direction of benefit, and view, plot and download the results.
launch_responder_analysis(...)launch_responder_analysis(...)
... |
Additional arguments passed to |
Called for its side effect of launching the app; invisibly returns
the value of shiny::runApp().
launch_responder_analysis()launch_responder_analysis()
Converts continuous outcomes (mean change, SD and sample size per arm, across
studies) into responder proportions and a range of between-arm effect
measures: the risk difference (RD), risk ratio (RR), odds ratio (OR) and
number needed to treat (NNT), under a parametric model for the change scores.
Responders are defined by a minimal important difference (MID) threshold (the
cut-point / "dichotomization" approach of Anzures-Cabrera, Sarpatwari and
Higgins, 2011). For a threshold-free alternative see responder_cles().
responder_analysis( data, mid, direction = c("higher", "lower"), method = c("individual", "weighted", "unweighted", "median", "smd"), se_method = c("binomial", "delta"), pooling = c("fixed", "random"), control = c("matched", "median"), tau_method = c("DL", "REML"), dist = c("normal", "lognormal", "t"), df = NULL, mid_sd = 0, ci_type = c("wald", "logit"), ci_method = c("wald", "hksj"), conf_level = 0.95 )responder_analysis( data, mid, direction = c("higher", "lower"), method = c("individual", "weighted", "unweighted", "median", "smd"), se_method = c("binomial", "delta"), pooling = c("fixed", "random"), control = c("matched", "median"), tau_method = c("DL", "REML"), dist = c("normal", "lognormal", "t"), df = NULL, mid_sd = 0, ci_type = c("wald", "logit"), ci_method = c("wald", "hksj"), conf_level = 0.95 )
data |
A data frame with one row per study and columns |
mid |
Single finite number: the minimal important difference threshold. |
direction |
|
method |
Methods to compute: any of |
se_method |
Per-study SE model for |
pooling |
|
control |
Baseline-risk rule for the summary methods ( |
tau_method |
Between-study variance estimator when |
dist |
Change-score distribution: |
df |
Degrees of freedom when |
mid_sd |
Optional standard deviation of the MID threshold; when |
ci_type |
|
ci_method |
Random-effects interval method: |
conf_level |
Confidence level (default |
A data frame with one row per requested method and columns: method,
pooling, k, p_e, p_c, rd/rd_lb/rd_ub, rr/rr_lb/rr_ub,
or/or_lb/or_ub, nnt/nnt_lb/nnt_ub, var_rd, and the
heterogeneity statistics tau2, i2, q, q_p, pi_lb, pi_ub (for the
pooled methods). Proportions, risk differences and CLES are on the
proportion scale; multiply by 100 for percentages.
individualDichotomize each study, then pool the per-study effect
measures (fixed or random effects). The most defensible option; the
per-study SE follows se_method.
weightedPool the mean change by inverse variance and the SD by the within-study pooled SD, dichotomize the pooled summaries, and obtain variances by the delta method.
unweighted, median
Dichotomize the arithmetic mean / median of
the study means and SDs. Summaries with no variance model: intervals are
NA.
smdPool the standardized mean difference (Hedges' g), bridge to an
odds ratio via the logistic link (lnOR = (pi / sqrt(3)) g), and combine
with the weighted-pooled control responder rate to recover risks. The
second approach of the reference; not included by default.
For the summary methods (median, unweighted, weighted) the control
proportion is, by default, pooled the same way as the experimental arm
(control = "matched"). Set control = "median" to instead take the baseline
risk from the median control arm for every summary method, as in the
Sofi-Mahmudi (2024) simulation study; the experimental arm is still pooled by
the chosen method. Because the median control arm carries no sampling-variance
model, control = "median" reports point estimates only (no intervals) for
the summary methods. The individual and smd methods pool per-study
contrasts and ignore control.
Sofi-Mahmudi A (2024). Identifying an optimal strategy for converting pain as a continuous outcome to a responder analysis. Master's thesis, McMaster University. https://hdl.handle.net/11375/30210
Thorlund K, Walter SD, Johnston BC, Furukawa TA, Guyatt GH (2011). Pooling health-related quality of life outcomes in meta-analysis: a tutorial and review of methods for enhancing interpretability. Research Synthesis Methods, 2(3), 188 to 203. doi:10.1002/jrsm.46
Anzures-Cabrera J, Sarpatwari A, Higgins JPT (2011). Expressing findings from meta-analyses of continuous outcomes in terms of risks. Statistics in Medicine, 30(25), 2867 to 2880. doi:10.1002/sim.4298
responder_rd_individual(), responder_cles(),
responder_proportions()
responder_analysis(sample_responder_data, mid = 1) # Random-effects individual method with relative measures: responder_analysis(sample_responder_data, mid = 1, method = "individual", pooling = "random")responder_analysis(sample_responder_data, mid = 1) # Random-effects individual method with relative measures: responder_analysis(sample_responder_data, mid = 1, method = "individual", pooling = "random")
A threshold-free responder-type measure: the probability that a randomly
chosen treated patient has a better change score than a randomly chosen
control. Under a Normal model this is exact,
with
(the sign is flipped when direction = "lower"). Per-study values
are pooled by fixed- or random-effect inverse variance and back-transformed,
so no minimal important difference is required.
responder_cles( data, direction = c("higher", "lower"), pooling = c("fixed", "random"), tau_method = c("DL", "REML"), ci_method = c("wald", "hksj"), conf_level = 0.95 )responder_cles( data, direction = c("higher", "lower"), pooling = c("fixed", "random"), tau_method = c("DL", "REML"), ci_method = c("wald", "hksj"), conf_level = 0.95 )
data |
A data frame with columns |
direction |
|
pooling |
|
tau_method |
Between-study variance estimator for random effects:
|
ci_method |
Random-effects interval method: |
conf_level |
Confidence level (default |
A list with:
Per-study data frame: study, delta, cles, cles_lb,
cles_ub.
Pooled CLES and its interval.
Pooled standardized difference and its SE.
Heterogeneity statistics; the prediction interval is back-transformed to the CLES scale.
Settings echoed back.
McGraw KO, Wong SP (1992). A common language effect size statistic. Psychological Bulletin, 111(2), 361 to 365.
cles <- responder_cles(sample_responder_data) cles$clescles <- responder_cles(sample_responder_data) cles$cles
Estimates, for each study arm, the probability that a patient's change score crosses the minimal important difference (MID) threshold under a parametric model for the change scores, together with a delta-method (sampling) variance for that probability.
responder_proportions( change, sd, n, mid, direction = c("higher", "lower"), dist = c("normal", "lognormal", "t"), df = NULL )responder_proportions( change, sd, n, mid, direction = c("higher", "lower"), dist = c("normal", "lognormal", "t"), df = NULL )
change |
Numeric vector of mean change scores. |
sd |
Numeric vector of standard deviations ( |
n |
Numeric vector of sample sizes ( |
mid |
Single finite number: the minimal important difference threshold. |
direction |
|
dist |
Change-score distribution: |
df |
Degrees of freedom when |
A data frame with one row per input element and columns p
(responder probability) and var_p (delta-method variance).
Thorlund K, Walter SD, Johnston BC, Furukawa TA, Guyatt GH (2011). Pooling health-related quality of life outcomes in meta-analysis: a tutorial and review of methods for enhancing interpretability. Research Synthesis Methods, 2(3), 188 to 203. doi:10.1002/jrsm.46
Anzures-Cabrera J, Sarpatwari A, Higgins JPT (2011). Expressing findings from meta-analyses of continuous outcomes in terms of risks. Statistics in Medicine, 30(25), 2867 to 2880. doi:10.1002/sim.4298
responder_proportions( change = c(0.96, 0.79, 1.02), sd = c(1.26, 1.28, 1.34), n = c(43, 139, 156), mid = 1 )responder_proportions( change = c(0.96, 0.79, 1.02), sd = c(1.26, 1.28, 1.34), n = c(43, 139, 156), mid = 1 )
Dichotomizes each study at the MID threshold and returns the per-study
responder risk difference (experimental minus control) with a confidence
interval. Building block for the "individual" method of
responder_analysis(); also feeds the forest plot and per-study table.
responder_rd_individual( data, mid, direction = c("higher", "lower"), se_method = c("binomial", "delta"), conf_level = 0.95, dist = c("normal", "lognormal", "t"), df = NULL, mid_sd = 0 )responder_rd_individual( data, mid, direction = c("higher", "lower"), se_method = c("binomial", "delta"), conf_level = 0.95, dist = c("normal", "lognormal", "t"), df = NULL, mid_sd = 0 )
data |
A data frame with one row per study and columns |
mid |
Single finite number: the minimal important difference threshold. |
direction |
|
se_method |
Per-study SE model for |
conf_level |
Confidence level (default |
dist |
Change-score distribution: |
df |
Degrees of freedom when |
mid_sd |
Optional standard deviation of the MID threshold; when |
A data frame with one row per study and columns study, p_e,
p_c, rd, se, ci_lb, ci_ub (proportion scale).
responder_rd_individual(sample_responder_data, mid = 1)responder_rd_individual(sample_responder_data, mid = 1)
A small illustrative dataset of three trials reporting continuous change scores per arm. Used in examples, the bundled Shiny app and the package tests. Values are fictional but plausible.
sample_responder_datasample_responder_data
A data frame with 3 rows and 7 columns:
Study identifier.
Mean change in the experimental arm.
Standard deviation of change in the experimental arm.
Sample size of the experimental arm.
Mean change in the control arm.
Standard deviation of change in the control arm.
Sample size of the control arm.
responder_analysis(sample_responder_data, mid = 1)responder_analysis(sample_responder_data, mid = 1)
Per-study change in pain on a 0-10 cm visual analogue scale (VAS) for an
exercise-therapy arm versus a control arm, from the 20 randomized trials
pooled for the VAS outcome by Li, Bao, Wang and Zhao (2025). The change scores
are post minus baseline VAS, so a more negative value is a larger pain
reduction; analyze with direction = "lower" and a negative MID equal to the
required reduction (for example mid = -1.5 for a 1.5 cm responder threshold).
vas_painvas_pain
A data frame with 20 rows and 7 columns:
Study label (first author and year).
Mean VAS change in the exercise (experimental) arm.
Standard deviation of the change in the exercise arm.
Exercise-arm sample size.
Mean VAS change in the control arm.
Standard deviation of the change in the control arm.
Control-arm sample size.
Li Z, Bao Z, Wang S, Zhao M (2025). Meta-analysis of the best exercise mode and dose study for improving spinal health. Frontiers in Sports and Active Living, 7, 1614906. doi:10.3389/fspor.2025.1614906. Figure 3 (VAS pain). Reproduced under the Creative Commons Attribution License (CC BY 4.0); the original authors and journal are credited as required.
# Proportion achieving at least a 1.5 cm VAS reduction (responder), # exercise versus control, random-effects with HKSJ intervals. responder_analysis(vas_pain, mid = -1.5, direction = "lower", pooling = "random", ci_method = "hksj")# Proportion achieving at least a 1.5 cm VAS reduction (responder), # exercise versus control, random-effects with HKSJ intervals. responder_analysis(vas_pain, mid = -1.5, direction = "lower", pooling = "random", ci_method = "hksj")