Files
tte-surgery/pvisim/inst/params/dgp_default.yml
T

130 lines
6.5 KiB
YAML

# Every number that defines the simulated world. Analysis plan v1.0, section 5.
# Time unit: month. Hazards are monthly, on the logit scale.
# Starting values are placeholders, to be tuned by calibration
# (simulations/01_calibrate.R, targets in plan section 5.4).
# Physician traits (skill k, style s) and patient frailty F are standard normal;
# their influence is set by the coefficients that multiply them.
size:
n_patients: 50000
n_physicians: 1500
panel_sdlog: 1.0 # lognormal panel weights; median panel about 20 at n = 50,000
months: 60 # follow-up months 0-59
window: 6 # strategy A: PVI in months 0-5
physician:
rho_skill_style: -0.3 # corr(k, s). Has no effect unless skill matters (world W1)
obl_intercept: 0.0 # logit P(office-based lab / ASC); about 50% of physicians
obl_style: 0.8 # high-style physicians more often work in OBL/ASC
patient:
age_min: 66
age_shape: 2.5 # age = 66 + Gamma(shape, scale); mean about 76
age_scale: 4.0
p_female: 0.50
p_black: 0.10
# comorbidities: logit P = qlogis(prev) + age_coef * (age - 76) / 10 + frailty_coef * F
comorbidity:
diabetes: {prev: 0.40, age_coef: -0.10, frailty_coef: 0.4}
ckd: {prev: 0.20, age_coef: 0.30, frailty_coef: 0.5}
chf: {prev: 0.20, age_coef: 0.40, frailty_coef: 0.6}
copd: {prev: 0.25, age_coef: 0.10, frailty_coef: 0.4}
prior_cvd: {prev: 0.45, age_coef: 0.20, frailty_coef: 0.3}
smoking: {prev: 0.25, age_coef: -0.40}
year_min: 2015
year_max: 2019
severity: # latent Z_t: walking limitation / ABI on a standard scale
z0_diabetes: 0.3
z0_smoking: 0.3
z0_ckd: 0.2
z0_sd: 1.0
r0: 0.02 # mean drift per month
r_diabetes: 0.01
r_smoking: 0.01
r_sd: 0.01 # patient-specific progression rate
eps_sd: 0.05 # month-to-month noise
treatment:
window: # elective PVI hazard, months 0-5, among the eligible
intercept: -5.4
z: 0.9 # confounding by indication
frailty: -0.3 # frail patients are less often offered PVI
age10: -0.3
diabetes: 0.1
ckd: -0.1
smoking: 0.1
style: 0.5 # physician style; world W2 sets it to the strong level
obl: 0.3
year: 0.05 # per calendar year after year_min
deferred: # elective PVI hazard from month 6 on (deferral / crossover)
intercept: -7.2
z: 0.0 # world W4 makes deferral severity-driven
style: 0.5
obl: 0.3
effect: # what a PVI does. Set by the truth scenario
relief: 0.0 # immediate drop in Z at PVI
kappa: 0.0 # extra Z drift per month after PVI
skill_kappa: 0.0 # kappa * exp(-skill_kappa * k): skill slows post-PVI progression
outcomes:
death: {intercept: -5.0, age10: 0.7, chf: 0.4, ckd: 0.4, copd: 0.3, frailty: 0.4, z: 0.1, clti: 0.8}
clti: {intercept: -6.6, z: 0.6, diabetes: 0.4, ckd: 0.3, smoking: 0.3, frailty: 0.2}
clti_false_code: {intercept: -9.0, style: 0.0} # factor 3 sets style
amputation: {intercept: -8.5, clti: 3.0, diabetes: 0.4, ckd: 0.4, z: 0.2}
bypass: {intercept: -7.8, z: 0.5}
repeat_revasc: {intercept: -5.3, skill: 0.0, style: 0.0, z: 0.2} # only after the index PVI
clti_revasc: {intercept: -4.5} # PVI after CLTI (not elective); most CLTI patients get bypass, tibial work, amputation or nothing
negative_controls: # never depend on PVI
nco1: {intercept: -6.75, frailty: 0.5, smoking: 0.4, age10: 0.3, z: 0.3} # hip fracture / pneumonia; z = PVI-free severity (D53)
nco2: {intercept: -7.1, style: 0.8, venous: 0.5} # varicose-vein ablation
nce: {intercept: -5.7, style: 0.8, frailty: -0.2} # low-value procedure, months 0-5
measurement: # what the analyst sees. World W5 switches to claims proxies
severity: exact # exact: analyst sees Z_t. proxy: only visit/testing counts. noisy: Z_t + error (EHR/registry)
noise_sd: 0.75 # noisy: SD of the monthly measurement error; Z_t has SD about 1 at diagnosis, so cor(observed, true) is about 0.8
proxy_intercept: -1.0 # monthly count ~ Poisson(exp(proxy_intercept + proxy_z * Z_t))
proxy_z: 0.5
proxy_window: 3 # observed severity = log1p(sum of counts over the last 3 months)
frailty_reliability: 1.0 # frailty index = sqrt(rel) * F + sqrt(1 - rel) * noise
smoking: true # true: analyst sees true smoking. coded: sensitivity / specificity below
smoking_sens: 0.6
smoking_spec: 0.98
worlds: # one factor at a time (plan section 5.2, D24). Overrides on the default.
# Intercepts are then re-solved per world by calibration, so every world
# matches the same Medicare targets unless `calibration_targets` says otherwise.
W0: {}
W1:
effect: {skill_kappa: 0.5}
outcomes: {repeat_revasc: {skill: -0.6}}
W1_rho0:
physician: {rho_skill_style: 0.0}
effect: {skill_kappa: 0.5}
outcomes: {repeat_revasc: {skill: -0.6}}
W2:
treatment: {window: {style: 1.6}, deferred: {style: 1.6}}
W3:
treatment: {window: {style: 1.6}, deferred: {style: 1.6}}
outcomes: {clti_false_code: {style: 0.8}, repeat_revasc: {style: 0.6}}
W4: # deferral common (as in trial conservative arms) and severity-driven
treatment: {deferred: {z: 0.8}}
calibration_targets: {late_not: 0.15}
W5:
measurement: {severity: proxy, frailty_reliability: 0.4, smoking: coded}
WE: # EHR/registry-like: severity recorded (ABI, symptom class) but with error (D55)
measurement: {severity: noisy, frailty_reliability: 0.7, smoking: true}
WR:
effect: {skill_kappa: 0.5}
treatment: {window: {style: 1.6}, deferred: {style: 1.6, z: 0.8}} # deferral at the Sorber rate, but severity-driven
outcomes: {repeat_revasc: {skill: -0.6, style: 0.6}, clti_false_code: {style: 0.8}}
measurement: {severity: proxy, frailty_reliability: 0.4, smoking: coded}
scenarios: # truth scenarios (plan section 5.3, D34)
"null": {effect: {relief: 0.0, kappa: 0.0}} # sharp disease null
harm: {effect: {relief: 0.3, kappa: 0.039}} # W0: disease-composite RD(A-B1) +5.1 pp at 60 months
benefit_harm: {effect: {relief: 2.0, kappa: 0.075}} # W0: RD -1.2 pp at 24 months, +3.1 pp at 60
# tuned in W0 with simulations/explore_scenarios.R (2e5 patients); the same mechanism is used in every world