rmorie implements every
statistical algorithm it exposes natively — this vignette walks the
whole pipeline on one simulated study using only
library(rmorie). No MatchIt, no survey, no DoubleML, no
dagitty, no fixest: each step below runs on an engine that lives in this
package and is cross-validated against the reference implementation in
tests/cross/.
A simulated observational study: three confounders drive both a binary treatment and a continuous outcome, with a true effect of 0.9.
Before any model: audit the categorical columns. Silent category-mapping errors — numeric codes imported without their labels, positional recodes, alphabetical releveling — have corrupted published disparity analyses for years at a time. rmorie makes them structurally impossible:
grp_codes <- sample(c("1", "2"), n, replace = TRUE) # an import hazard
morie_audit_categories(data.frame(group = factor(grp_codes)))
#> Categorical audit: 1 column(s)
#> group factor 2 level(s), reference '1'
#> !! HAZARD: all labels numeric-looking (1,2...): likely imported CODES whose value labels were lost; as.numeric() on this column returns level INDICES, not data
grp <- morie_safe_recode(grp_codes, c("1" = "Control", "2" = "Program"))
morie_crosstab_verify(grp_codes, grp,
c("1" = "Control", "2" = "Program"))dag <- morie_dag(
edges = c("re74 -> treat", "re74 -> re78",
"age -> treat", "age -> re78",
"educ -> treat", "educ -> re78",
"treat -> re78"),
exposure = "treat", outcome = "re78")
dag
#> morie causal DAG: 5 nodes, 7 edges
#> exposure: treat outcome: re78
#> re74 -> treat
#> re74 -> re78
#> age -> treat
#> age -> re78
#> educ -> treat
#> educ -> re78
#> treat -> re78Backdoor identification runs Bayes-Ball d-separation with the
canonical adjustment set (validated against dagitty in
tests/cross/):
morie_dag_estimate() routes the identified set into the
native estimators — here double machine learning (cross-fit ridge +
logit nuisances, Neyman-orthogonal score):
DoWhy-style robustness checks, all native — a placebo treatment should erase the effect; subsets and a random common cause should leave it stable:
The MRM flagship composes several native estimators on the same specification, applies a multiple-testing correction across them, pools an inverse-variance consensus, and renders the table with rmorie’s own renderer (text, markdown, LaTeX, or HTML):
eff <- morie_mrm_estimate_causal_effect(
d, "treat", "re78", id$adjustment_set,
methods = c("matching", "ate", "dml"))
#> Warning: categorical coding hazards in covariates [re74, age, educ] - run
#> morie_audit_categories(data) and fix before trusting these estimates.
#> Warning: Fewer control units than treated units; not all treated units will get
#> a match.
cat(morie_mrm_report(eff, format = "markdown"), sep = "\n")
#> | Method | Estimate | SE | 95% CI | p (adj.) |
#> |--------------------------|----------|--------|---------------|----------|
#> | matching (rmorie native) | 1.47*** | 0.105 | [1.26, 1.67] | 4.63e-38 |
#> | ipw ate (rmorie native) | 0.906*** | 0.18 | [0.553, 1.26] | 4.85e-07 |
#> | dml plr (rmorie native) | 0.908*** | 0.0881 | [0.735, 1.08] | 1.31e-24 |
#> Consensus (inverse-variance): 1.11 (SE 0.0631). holm correction; n = 600.tests/cross/
(one file per reference package) and its speed in
inst/benchmarks/.?morie_did_group_time_att,
?morie_synth_control, ?morie_rdd_sharp,
?morie_its, ?morie_iv_tsls.morie_crypto_pqc_inventory() reports the post-quantum
coverage of your build.