Skip to content
choxosPublic

About

R package, Shiny app, and browser tool for responder analysis of continuous outcomes

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Repository files navigation

respondeR respondeR hex logo

CRAN status R-CMD-check pkgdown Lifecycle: experimental License: GPL v3

respondeR re-expresses meta-analyses of continuous trial outcomes in terms of responders. Clinicians and patients reason about "how many people get better", not about standardized mean differences. It uses only the summary statistics that trials usually report: the mean change, standard deviation and sample size in each arm. From these respondeR estimates the proportion of patients whose change crosses a minimal important difference (MID) threshold, and contrasts the arms as a risk difference (RD), risk ratio (RR), odds ratio (OR) or number needed to treat (NNT).

It follows the interpretability tutorial of Thorlund, Walter, Johnston, Furukawa & Guyatt (2011), implementing the cut-point ("dichotomization") and standardized-mean-difference conversions it reviews, and adds a threshold-free common-language effect size. The estimation methods were evaluated in a simulation study (Sofi-Mahmudi, 2024).

Try it in the browser (no install): https://choxos.github.io/respondeR/app/ (a separate implementation; the R package is the reference)

Documentation: https://choxos.github.io/respondeR/

Installation

# From CRAN
install.packages("respondeR")

# Development version from GitHub
# install.packages("remotes")
remotes::install_github("choxos/respondeR")

Quick start

library(respondeR)

# Built-in example: three trials of a continuous change score
sample_responder_data
#>     study  change_e     sd_e n_e     change_c     sd_c n_c
#> 1 Study 1 0.9581395 1.257593  43  0.217777778 1.195501  45
#> 2 Study 2 0.7920863 1.281364 139  0.003448276 1.324629 145
#> 3 Study 3 1.0230769 1.341201 156 -0.041975309 1.263178 162

# Proportion of responders (change > MID of 1) and between-arm contrasts
responder_analysis(sample_responder_data, mid = 1)
#> Responder analysis (respondeR)
#>   MID = 1 (a higher change is a response); k = 3 studies; fixed
#>   effects; delta per-study variance
#>   Percentages; 95% confidence intervals.
#>
#>           Method   PE   PC                  RD                  RR
#>       Individual    -    - 25.5 (20.0 to 31.0) 2.15 (1.79 to 2.58)
#>    Weighted mean 47.6 22.1 25.5 (20.0 to 31.0) 2.16 (1.80 to 2.59)
#>  Unweighted mean 47.7 22.8                24.9                2.09
#>           Median 48.7 21.5                27.2                2.26
#>                   OR                   NNT
#>  3.20 (2.45 to 4.18) NNTB 3.9 (3.2 to 5.0)
#>  3.21 (2.46 to 4.19) NNTB 3.9 (3.2 to 5.0)
#>                 3.09              NNTB 4.0
#>                 3.46              NNTB 3.7

The result is a data frame (res$rd, as.data.frame(res) for every column) with summary() and plot() (forest plot) methods. Proportions and risk differences are stored on the [0, 1] scale.

# Random effects with the small-k Hartung-Knapp-Sidik-Jonkman interval
res <- responder_analysis(sample_responder_data, mid = 1, method = "individual",
                          pooling = "random", ci_method = "hksj_adhoc")

# How the result depends on the MID
plot(responder_curve(sample_responder_data, mids = seq(0, 2, by = 0.25)), at = 1)

# GRADE summary-of-findings rows per 1000 patients
responder_sof(res, control_risk = c(0.1, 0.3))

# Threshold-free: how often does a treated patient do better than a control?
responder_cles(sample_responder_data)

Data format

One row per study, with these columns (the experimental arm is _e, the control arm _c):

Column Meaning
study Study (comparison) label
change_e Mean change in the experimental arm
sd_e SD of change in the experimental arm
n_e Experimental arm sample size
change_c Mean change in the control arm
sd_c SD of change in the control arm
n_c Control arm sample size
trial Optional: trial label shared by the comparisons of a multi-arm trial

Comparisons of one multi-arm trial that reuse a control arm are marked by a shared trial value; respondeR then splits that control arm among them so its patients are not counted twice. Missing change-score SDs can be reconstructed with impute_change_sd().

Two datasets ship with the package: sample_responder_data (a small toy example) and vas_pain, a real meta-analysis of 20 exercise-versus-control comparisons for spinal health pooled on the VAS pain scale (Li et al., 2025, reproduced under CC BY 4.0). Because VAS change is negative when pain improves, analyze it with direction = "lower":

# Proportion reaching a 1.5 cm VAS reduction, exercise vs control
responder_analysis(vas_pain, mid = -1.5, direction = "lower",
                   pooling = "random", ci_method = "hksj_adhoc")

Methods

A responder is a patient whose change crosses the MID. Under a Normal model an arm's responder probability is p = Phi((mu - mid) / sigma) (for direction = "higher"). The methods differ in how the per-arm summaries are pooled across studies before, or after, dichotomizing.

Method What it pools Variance / CI Notes
individual Per-study contrasts (fixed or random effects) Yes Recommended; comparisons stay within trials
weighted Pooled control mean plus pooled within-study mean difference Delta method Pool-then-dichotomize, randomization kept
unweighted Arithmetic mean of study means and SDs None Descriptive (point estimate)
median Median of study means and SDs None Descriptive (point estimate)
smd Standardized mean difference to odds ratio Yes Logistic bridge; opt-in

Responder probabilities are evaluated on the log scale, so risk and odds ratios stay exact even in the far tails. With fixed effects the risk difference uses sample-size weights, which a study with probabilities near 0 or 1 cannot dominate, and a warning flags any study that holds more than half of the weight. control = "median" takes the baseline risk from the median control arm, as in the simulation study of Sofi-Mahmudi (2024); the result is then a point estimate.

Effect measures. Every method reports the absolute risk difference, the relative risk ratio and odds ratio, and the number needed to treat in the Altman form (NNTB for benefit, NNTH for harm). responder_cles() adds the threshold-free common-language effect size.

Options. pooling = "random" (DerSimonian-Laird or REML) with ci_method = "wald", "hksj" or "hksj_adhoc"; se_method ("delta" or "binomial"); rd_weights; control for the baseline-risk rule; ci_type = "logit" for bounded MOVER intervals; mid_sd to propagate MID uncertainty (added once, after pooling); and dist = "lognormal" or "t" for non-Normal change scores.

Version 0.2.0 corrects several methods, so its numbers differ from 0.1.0; see NEWS.md.

From a fitted meta-analysis

Already have a continuous meta-analysis saved in an R object? Pass it straight to responder_analysis(). A meta::metacont object carries both arms, so the full analysis runs; a metafor::rma fit carries only the pooled effect, so you give a baseline control responder risk. respondeR reads the object with base R, so the source package need not be attached, and it adds no new dependencies.

# meta::metacont object: full analysis
responder_analysis(metacont_fit, mid = 1)

# metafor::rma object (SMD or MD): pooled effect + a named baseline control risk
responder_analysis(rma_fit, baseline = 0.22)
responder_analysis(rma_fit, baseline = 0.22, direction = "lower")  # e.g. pain

# Just a pooled estimate from a paper:
responder_from_effect(0.5, se = 0.1, measure = "SMD", baseline = 0.25)

The fit's own choices carry over: excluded studies are dropped, random-effects and Hartung-Knapp settings are reused, and an rma fit's interval and confidence level are kept. See vignette("meta-analysis-objects"). Support for netmeta and multinma objects is planned for a later release.

Key functions

Function Purpose
responder_analysis() Pooled responder proportions and effect measures (data frame or fitted MA object)
responder_from_effect() Convert a pooled SMD/MD + baseline to responder measures
as_responder_data() Extract the arm-summary data frame from an MA object
responder_curve() The analysis across a range of MID thresholds
responder_sof() GRADE summary-of-findings rows per 1000 patients
impute_change_sd() Reconstruct change-score SDs (Cochrane Handbook)
responder_rd_individual() Per-study risk differences (forest-plot input)
responder_proportions() Per-arm responder probabilities with variances
responder_cles() Threshold-free common-language effect size
format_responder_results() Display-ready formatting
launch_responder_analysis() Launch the Shiny application

The Shiny application

The package bundles a point-and-click app: upload a CSV or use the bundled example, set the MID and direction, choose methods and options, and view the results table, per-study forest plot and CLES, with CSV downloads. Notes and warnings from the analysis are listed under the results.

launch_responder_analysis()

A browser version (no R, no install) runs at https://choxos.github.io/respondeR/app/; it is a separate implementation that does not yet include the 0.2.0 changes.

Vignettes

  • vignette("respondeR"): getting started; data format, a worked example, and interpreting the output.
  • vignette("methodology"): the statistics in full; the cut-point approach, each method and its variance, the relative measures, CLES, the SMD bridge, heterogeneity, MID uncertainty, multi-arm trials, assumptions and a method-choice guide.
  • vignette("meta-analysis-objects"): responder analysis from a fitted meta or metafor meta-analysis, or from a single pooled estimate.

References

Sofi-Mahmudi, A. (2024). Identifying an optimal strategy for converting pain as a continuous outcome to a responder analysis [Master's thesis, McMaster University]. MacSphere. https://hdl.handle.net/11375/30210

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: 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, 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

McGraw, K. O., & Wong, S. P. (1992). A common language effect size statistic. Psychological Bulletin, 111(2), 361 to 365.

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.

Bundled data:

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 (the vas_pain dataset, Figure 3, reproduced under CC BY 4.0).

Citing respondeR

citation("respondeR")

The logo

The hex logo shows two Normal change-score distributions, control and experimental, split by a dashed MID cut-point. The shaded tails beyond the cut are the responder proportions in each arm; their contrast is the risk difference. That is responder analysis in one picture.

Author

Ahmad Sofi-Mahmudi

License

GPL-3. See https://www.gnu.org/licenses/gpl-3.0 for the full license text.

About

R package, Shiny app, and browser tool for responder analysis of continuous outcomes

Topics

Resources

Stars

3 stars

Watchers

1 watching

Forks

Releases

Contributors

Languages