Source code for sctrial.stats.sensitivity

from __future__ import annotations

import math


[docs] def e_value_rr( estimate: float, *, ci_lower: float | None = None, ci_upper: float | None = None, ) -> tuple[float, float | None]: """Compute the E-value for a risk ratio estimate (VanderWeele & Ding). Ref: VanderWeele, Tyler J., and Peng Ding. "Sensitivity analysis in observational research: introducing the E-value." Annals of internal medicine 167.4 (2017): 268-274. Parameters ---------- estimate Risk ratio (RR) estimate (>0). ci_lower, ci_upper Optional confidence interval bounds on the RR scale. Returns ------- (e_value, e_value_ci) E-value for the point estimate and for the confidence limit closest to 1. """ if estimate <= 0: raise ValueError("estimate must be > 0 for E-value.") def _e_value(rr: float) -> float: """Compute the E-value.""" if rr < 1: rr = 1 / rr return rr + math.sqrt(rr * (rr - 1)) if ci_lower is not None and ci_upper is not None: if ci_lower <= 0 or ci_upper <= 0: raise ValueError("CI bounds must be > 0 for E-value.") if ci_lower > ci_upper: raise ValueError("ci_lower must be <= ci_upper.") if not (ci_lower <= estimate <= ci_upper): raise ValueError("estimate must fall within [ci_lower, ci_upper].") e_est = _e_value(estimate) e_ci = None if ci_lower is not None and ci_upper is not None: # use CI bound closest to 1 if estimate >= 1: ci = ci_lower else: ci = ci_upper if ci is not None and ci > 0: e_ci = _e_value(ci) return e_est, e_ci