Learn R Programming

DMAR (version 1.0.0)

responder_analysis: Responder Analysis: Who Cleared the Threshold, by Group

Description

The clinical and behavioral endpoint that mean differences hide: the proportion of each group whose outcome reaches a meaningful threshold (a minimal clinically important difference, a remission cut, a mastery criterion). For each group the function reports the responder count and proportion with a Wilson confidence interval; with exactly two groups it adds the risk difference with the Newcombe (1998) score-based hybrid interval and the number needed to treat; and across any number of groups it reports the omnibus chi square test of equal responder proportions. An optional sweep repeats the analysis over a grid of thresholds, making explicit how conclusions depend on where the line is drawn, disclosing the threshold dependence that any single-threshold claim leaves implicit.

Usage

responder_analysis(
  x,
  group,
  threshold,
  direction = c("ge", "le"),
  conf_level = 0.95,
  sweep = NULL
)

Value

A tidy wide data.frame (class dmar_tbl). One row per group with group, n, responders,

estimate (the proportion), lower_limit,

upper_limit; with two groups, a difference row (second level minus first) and an nnt row; and a final

omnibus row carrying chi_square, df, and

p_value (columns that are NA on the other rows). When

sweep is supplied, the same table is stacked per threshold with a leading threshold column.

Arguments

x

Numeric vector of outcomes (for example, change scores).

group

Group labels, one per observation (coerced to factor; the first level is the reference for the two-group difference).

threshold

The cut defining response.

direction

"ge" (default): a responder has x >= threshold; "le": x <= threshold (for outcomes where lower is better).

conf_level

Confidence level for all intervals. Defaults to 0.95.

sweep

Optional numeric vector of additional thresholds; the analysis is repeated at each and stacked with a leading threshold column.

Author

Ken Kelley [email protected]

Details

Per-group intervals are Wilson score intervals (ci_proportion). The two-group risk difference uses Newcombe's method 10: the difference interval is assembled from the two Wilson limits, which keeps it inside [-1, 1] and well behaved at boundary counts. The number needed to treat is \(1/|\Delta|\), with its interval from the inverted difference limits when the difference interval excludes zero; when it includes zero the NNT interval is reported as NA (the interval is disjoint and an interval on the NNT scale would mislead; Altman, 1998). Dichotomizing throws away information, so a responder analysis complements, never replaces, the analysis of the continuous outcome (Maxwell, Delaney, & Kelley, 2027).

References

Altman, D. G. (1998). Confidence intervals for the number needed to treat. BMJ, 317(7168), 1309--1312. tools:::Rd_expr_doi("10.1136/bmj.317.7168.1309")

Newcombe, R. G. (1998). Interval estimation for the difference between independent proportions: Comparison of eleven methods. Statistics in Medicine, 17(8), 873--890. tools:::Rd_expr_doi("10.1002/(SICI)1097-0258(19980430)17:8<873::aid-sim779>3.0.CO;2-I")

Maxwell, S. E., Delaney, H. D., & Kelley, K. (2027). Designing experiments and analyzing data: A model comparison perspective (4th ed.). Routledge.

See Also

ci_proportion for the per-group interval; nnt_from_smd for the model-based route to the number needed to treat from a standardized mean difference; cliff_delta and proportion_of_superiority for dominance-style effect sizes on the continuous outcome.

Other effect size estimates: cles(), cliff_delta(), correction_for_attenuation(), eta_squared(), eta_squared_generalized(), eta_squared_partial(), expected_partial_r(), expected_r(), expected_smd(), nnt_from_smd(), omega_squared(), omega_squared_partial(), probability_of_superiority_paired(), proportion_of_superiority(), smd_trimmed()

Examples

Run this code
# A two-arm trial: change scores, response defined as a gain of 10+.
set.seed(113)
change <- c(rnorm(60, 8, 9), rnorm(60, 13, 9))
arm    <- rep(c("control", "treatment"), each = 60)
responder_analysis(change, arm, threshold = 10)

# How threshold-dependent is that conclusion?
responder_analysis(change, arm, threshold = 10, sweep = c(5, 15))

Run the code above in your browser using DataLab