*! dpath_equity: Distributive equity diagnostics for decision paths *! Version 1.0.0 Subir Hait, Michigan State University (2026) /* dpath equity, id(idvar) time(timevar) by(groupvar) [ref(reflevel)] Computes equity diagnostics via standardized mean differences (SMDs) across path descriptors (dosage, switching rate, onset, duration, DRI) between group levels and a reference group. SMD = (mean_g - mean_ref) / SD_pooled |SMD| < 0.10 : negligible difference (equity achieved) |SMD| 0.10-0.20 : small |SMD| > 0.20 : meaningful inequity Results stored in r(): r(smd_dosage) : SMD for dosage r(smd_switch) : SMD for switching rate r(smd_onset) : SMD for onset r(smd_duration) : SMD for duration r(DRI_ref) : DRI for reference group */ program define dpath_equity, rclass version 14.0 syntax , id(varname) time(varname) BY(varname) [REF(string)] // ── Check prerequisites ─────────────────────────────────────────────── foreach v in _dp_dosage _dp_switch _dp_onset _dp_duration { capture confirm variable `v' if _rc { di as error "Variable `v' not found. Run {cmd:dpath build} first." exit 111 } } capture confirm variable `by' if _rc { di as error "Group variable `by' not found." exit 111 } preserve // Keep one row per unit quietly bysort `id' (`time'): keep if _n == _N // ── Get group levels ────────────────────────────────────────────────── quietly levelsof `by', local(grplevels) local n_groups : word count `grplevels' if `n_groups' < 2 { di as error "Group variable `by' has fewer than 2 levels." exit 198 } // Reference group: use first level if not specified if "`ref'" == "" { local ref : word 1 of `grplevels' } // Check ref is valid local ref_found 0 foreach g of local grplevels { if "`g'" == "`ref'" local ref_found 1 } if !`ref_found' { di as error "Reference level `ref' not found in `by'." exit 198 } // ── Compute overall SD for each metric ─────────────────────────────── foreach metric in _dp_dosage _dp_switch _dp_onset _dp_duration { quietly summarize `metric' local sd_`metric' = r(sd) } // ── Reference group stats ───────────────────────────────────────────── quietly summarize _dp_dosage if `by' == "`ref'", meanonly local mean_dosage_ref = r(mean) quietly summarize _dp_switch if `by' == "`ref'", meanonly local mean_switch_ref = r(mean) local dri_ref = 1 - `mean_switch_ref' quietly summarize _dp_onset if `by' == "`ref'", meanonly local mean_onset_ref = r(mean) quietly summarize _dp_duration if `by' == "`ref'", meanonly local mean_dur_ref = r(mean) quietly count if `by' == "`ref'" local n_ref = r(N) // ── Display header ──────────────────────────────────────────────────── di as text _newline "{hline 65}" di as result " dpath equity — Equity Diagnostics" di as text "{hline 65}" di as text " Group variable : " as result "`by'" di as text " Reference group : " as result "`ref'" /// " (N=" `n_ref' ")" di as text "{hline 65}" di as text " Reference group descriptors:" di as text " Dosage : " as result %6.3f `mean_dosage_ref' di as text " Switch : " as result %6.3f `mean_switch_ref' di as text " DRI : " as result %6.3f `dri_ref' di as text " Onset : " as result %6.3f `mean_onset_ref' di as text " Duration : " as result %6.3f `mean_dur_ref' di as text "{hline 65}" di as text " Standardized Mean Differences (vs. `ref'):" di as text " {hline 60}" di as text " Group N Dosage Switch Onset Duration DRI" di as text " {hline 60}" // ── SMD for each non-reference group ───────────────────────────────── foreach g of local grplevels { if "`g'" == "`ref'" continue quietly count if `by' == "`g'" local ng = r(N) quietly summarize _dp_dosage if `by' == "`g'", meanonly local smd_dos = (`r(mean)' - `mean_dosage_ref') / max(`sd__dp_dosage', 0.0001) quietly summarize _dp_switch if `by' == "`g'", meanonly local ms_g = r(mean) local smd_sw = (`ms_g' - `mean_switch_ref') / max(`sd__dp_switch', 0.0001) local dri_g = 1 - `ms_g' quietly summarize _dp_onset if `by' == "`g'", meanonly local smd_on = (`r(mean)' - `mean_onset_ref') / max(`sd__dp_onset', 0.0001) quietly summarize _dp_duration if `by' == "`g'", meanonly local smd_dur = (`r(mean)' - `mean_dur_ref') / max(`sd__dp_duration', 0.0001) local dri_smd = `dri_g' - `dri_ref' di as text " " %-10s "`g'" " " as result %3.0f `ng' /// " " %6.3f `smd_dos' " " %6.3f `smd_sw' /// " " %6.3f `smd_on' " " %8.3f `smd_dur' /// " " %5.3f `dri_smd' } di as text " {hline 60}" di as text " Note: |SMD| < 0.10 negligible; 0.10-0.20 small; > 0.20 meaningful" // ── By-group mean table ─────────────────────────────────────────────── di as text _newline " Group-level means:" di as text " {hline 60}" di as text " Group N Dosage Switch Onset Duration DRI" di as text " {hline 60}" foreach g of local grplevels { quietly count if `by' == "`g'" local ng = r(N) quietly summarize _dp_dosage if `by' == "`g'", meanonly local md = r(mean) quietly summarize _dp_switch if `by' == "`g'", meanonly local ms = r(mean) local dr = 1 - `ms' quietly summarize _dp_onset if `by' == "`g'", meanonly local mo = r(mean) quietly summarize _dp_duration if `by' == "`g'", meanonly local mdu = r(mean) di as text " " %-10s "`g'" " " as result %4.0f `ng' /// " " %7.3f `md' " " %7.3f `ms' " " %6.3f `mo' /// " " %8.3f `mdu' " " %5.3f `dr' } di as text " {hline 60}" restore // ── Return scalars ──────────────────────────────────────────────────── return scalar DRI_ref = `dri_ref' end