Covariate-adjusted bivariate causal discovery via the Generative Exposure Model.
causalCovGEM implements the covariate-adjusted Generative Exposure Model
(CGEM) for determining causal direction between a pair of continuous
variables in the presence of an observed conditioning set Z. The same
machinery classifies the structural role of a candidate covariate relative
to a fixed exposure-outcome pair (confounder, mediator, or collider), which
supports covariate selection for Covariate Adaptive Randomization (CAR)
in clinical trial design.
The package accompanies:
Purkayastha, S. and Song, P.X.K. "Covariate-Adjusted Bivariate Causal Discovery in Clinical Studies." Statistica Sinica (under revision).
It is the R counterpart to
causalGEM, a Python/PyPI package
implementing the marginal (unconditional) Generative Exposure Model.
In the CGEM framework, a causal relationship is modeled as
Y = g(X, Z) + eps, eps _||_ X | Z
where X is the hypothesized cause, Z is an observed conditioning set,
g is a smooth generative map, and eps is independent noise given Z.
The conditional asymmetry criterion (CAC) is the extremum, over the
support of Z, of the conditional entropy gap
Delta(z) = H(X | Z = z) - H(Y | Z = z)
Its sign identifies the causal direction and the local dynamics of g
(expanding vs. contracting); testing it stratum-by-stratum additionally
localizes where a single globally specified direction breaks down.
# install.packages("remotes")
remotes::install_github("soumikp/causalCovGEM")library(causalCovGEM)
set.seed(1)
n <- 800
z1 <- runif(n); z2 <- runif(n)
x <- rbeta(n, shape1 = 1 + 5 * z1, shape2 = 1 + 5 * z2)
y <- (2 + z1 + z2) * x + rnorm(n, sd = 0.05) # true direction: x -> y
result <- run_cac_pair(x, y, data.frame(z1 = z1, z2 = z2), score = "none")
result$dynamics # "expanding"
result$cac # point estimate of the CAC
result$ci # confidence interval# baseline candidate: confounder screen
screen <- triage_candidate("Zj", E = e, O = o, Zj = zj,
temporal_status = "baseline", n_bins = 4)
screen$verdict # "confounder", "direction-heterogeneous", "uniform-reverse", or "inconclusive"
# intermediate candidate: mediator/collider test
result <- triage_covariate("Zj", E = e, Y = o, Zj = zj, cond_df = z_other,
temporal_status = "intermediate")
result$inferred_role # "confounder", "mediator", "collider", "heterogeneous", or "unclassifiable"See vignette("causalCovGEM-intro") and vignette("car-triage") for full
walkthroughs.
R/— the exported package API: conditional-entropy estimation (calculate_conditional_entropy_mv(),entropy_1d()), the CAC extremum test (analyze_entropy_difference()), summary scores for high-dimensional conditioning sets (gam_summary_score(),pca_summary_score(),cac_with_score()), edge orientation (run_cac_pair(),cgem_orient()), and covariate triage for CAR (triage_candidate(),triage_covariate(),triage_covariate2()).inst/simulation/— the paper's data-generating processes (dgp.R, mechanisms M1-M7c) and locally-runnable reproductions of the simulation study's key jobs (competitor benchmark, heterogeneity detection, and structural-role recovery). The full multi-method comparison (also benchmarking CAM, RESIT, bQCD, PC, and HC, which require cluster-specific installs) is archived verbatim underinst/simulation/cluster/.inst/analysis/— the Intern Health Study (IHS) application: data-build, confounder screen, mediator/collider test, and the main PHQ/GAD directionality analysis, runnable end-to-end against the bundled IHS data (inst/analysis/data/, CC BY 4.0, from ICPSR).inst/submission/— the manuscript's LaTeX source and PDF submissions (round 1 and round 2, including the response-to-reviewers letters), for provenance.
If you use this package, please cite the accompanying paper (full citation to be updated on publication):
Purkayastha, S. and Song, P.X.K. (2026). Covariate-Adjusted Bivariate
Causal Discovery in Clinical Studies. Statistica Sinica, under revision.
MIT © Soumik Purkayastha