D53: landmark on baseline covariates (month-5 version as landmark_m5), NCO-1 depends on PVI-free severity, physician-cluster bootstrap script
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
suppressPackageStartupMessages(library(data.table))
|
||||
a <- commandArgs(TRUE)
|
||||
indir <- if (length(a) >= 1) a[1] else "results/main/n50k"
|
||||
indir <- if (length(a) >= 1) a[1] else "results/main/n50k_v2"
|
||||
outdir <- "results/summary"
|
||||
dir.create(outdir, recursive = TRUE, showWarnings = FALSE)
|
||||
|
||||
@@ -32,7 +32,7 @@ d <- merge(d, tr[estimand == "rd_A_B1", .(world, scenario, outcome, ref = truth)
|
||||
# landmark and naive: own estimand = the paired oracle estimate in the same replicate (D47)
|
||||
orc <- d[variant == "oracle", .(world, scenario, rep, design, outcome, oracle = est)]
|
||||
d <- merge(d, orc, by = c("world", "scenario", "rep", "design", "outcome"), all.x = TRUE)
|
||||
d[design %in% c("landmark", "naive") & variant != "oracle", own := oracle]
|
||||
d[design %in% c("landmark", "landmark_m5", "naive") & variant != "oracle", own := oracle]
|
||||
d[analysis %like% "^nce", `:=`(own = 0, ref = 0)]
|
||||
d[, oracle := NULL]
|
||||
d[, `:=`(lo = est - 1.96 * se, hi = est + 1.96 * se)]
|
||||
@@ -59,7 +59,7 @@ fwrite(perf, file.path(outdir, "perf.csv"))
|
||||
# ---- negative controls as bias detectors (plan 10) ------------------------------------
|
||||
# One unit = world x scenario x design x variant x replicate. Bias is in the MALE RD
|
||||
# against the method's own estimand; a control "flags" when its 95% CI excludes 0.
|
||||
m <- d[analysis == "main" & variant %in% c("V1_ignore", "V2_cluster", "V3_random", "V4_within") &
|
||||
m <- d[analysis == "main" & design != "landmark_m5" & variant %in% c("V1_ignore", "V2_cluster", "V3_random", "V4_within") &
|
||||
contrast %in% c("early_none", "A_B1", "now_not")]
|
||||
u <- c("world", "scenario", "design", "variant", "rep")
|
||||
flag <- function(x) x$lo > 0 | x$hi < 0
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
# Physician-cluster bootstrap check of the model-based SEs (D28, reduced in D53).
|
||||
# Usage: Rscript simulations/05_bootstrap.R [reps] [B] [cores]
|
||||
# Writes results/bootstrap/<world>_<scenario>_rep<k>.csv: the estimate and the
|
||||
# bootstrap SD for each design, contrast and outcome (V1 point estimates).
|
||||
|
||||
pkgload::load_all("pvisim", quiet = TRUE)
|
||||
suppressPackageStartupMessages(library(data.table))
|
||||
a <- commandArgs(TRUE)
|
||||
reps <- if (length(a) >= 1) as.integer(a[1]) else 20L
|
||||
B <- if (length(a) >= 2) as.integer(a[2]) else 50L
|
||||
cores <- if (length(a) >= 3) as.integer(a[3]) else 11L
|
||||
cfg <- yaml::read_yaml("simulations/config/experiments.yml")
|
||||
n <- cfg$scales$draft$n_patients
|
||||
outdir <- "results/bootstrap"; dir.create(outdir, showWarnings = FALSE, recursive = TRUE)
|
||||
designs <- c("naive", "landmark", "landmark_m5", "ccw", "seq")
|
||||
outs <- c(male = "t_male", disease = "t_disease")
|
||||
|
||||
jobs <- CJ(world = c("W0", "WR"), scenario = c("null", "harm"), rep = seq_len(reps), sorted = FALSE)
|
||||
jobs[, file := file.path(outdir, sprintf("%s_%s_rep%03d.csv", world, scenario, rep))]
|
||||
todo <- jobs[!file.exists(file)]
|
||||
cat(sprintf("bootstrap: %d jobs, %d to do, B = %d, %d cores\n", nrow(jobs), nrow(todo), B, cores))
|
||||
res <- parallel::mclapply(seq_len(nrow(todo)), function(i) tryCatch({
|
||||
j <- todo[i]
|
||||
par <- load_params(j$world, j$scenario)
|
||||
rec <- simulate_records(par, rep = j$rep, n = n) # the same data as the main run's replicate
|
||||
bs <- rbindlist(lapply(seq_len(B), function(b)
|
||||
cbind(b = b, run_designs(bootstrap_records(rec, seed = 1e6 * j$rep + b), designs, "V1_ignore", outs))), fill = TRUE)
|
||||
out <- bs[, .(boot_se = sd(est, na.rm = TRUE), boot_mean = mean(est, na.rm = TRUE), B = sum(!is.na(est))),
|
||||
by = .(design, contrast, outcome)]
|
||||
fwrite(out[, `:=`(world = j$world, scenario = j$scenario, rep = j$rep)], j$file)
|
||||
NULL
|
||||
}, error = function(e) sprintf("%s/%s/%d: %s", todo$world[i], todo$scenario[i], todo$rep[i], conditionMessage(e))),
|
||||
mc.cores = cores, mc.preschedule = FALSE)
|
||||
err <- unlist(res[!vapply(res, is.null, TRUE)])
|
||||
cat(sprintf("done; %d errors\n", length(err))); if (length(err)) cat(head(err, 3), sep = "\n")
|
||||
@@ -2,11 +2,11 @@
|
||||
main:
|
||||
worlds: [W0, W1, W1_rho0, W2, W3, W4, W5, WR]
|
||||
scenarios: ["null", harm, benefit_harm]
|
||||
designs: [naive, landmark, ccw, seq]
|
||||
designs: [naive, landmark, landmark_m5, ccw, seq] # landmark_m5: also adjusts for month-5 severity (supplement, D53)
|
||||
variants: [V1_ignore, V3_random, V4_within] # V1 also yields V2 (cluster-robust SE)
|
||||
nce: true # negative-control exposure (landmark, CCW), D32/D36
|
||||
rct: [realistic, ideal]
|
||||
scales:
|
||||
smoke: {n_patients: 20000, reps: 1}
|
||||
draft: {n_patients: 50000, reps: 100, dir: n50k}
|
||||
final: {n_patients: 50000, reps: 200, dir: n50k} # extends the draft's replicates 1-100 to 200 (D51)
|
||||
draft: {n_patients: 50000, reps: 100, dir: n50k_v2} # v2: D53 (landmark baseline covariates, NCO-1 severity)
|
||||
final: {n_patients: 50000, reps: 200, dir: n50k_v2} # extends the draft's replicates 1-100 to 200 (D51)
|
||||
|
||||
Reference in New Issue
Block a user