Skip to contents

Splits the data by group_col and estimates an augmented inverse-probability-weighted average treatment effect inside each stratum, so that both nuisance models are allowed to differ across groups.

Usage

morie_gate(
  data,
  treatment,
  outcome,
  covariates,
  group_col,
  propensity_col = NULL,
  trim = c(0.01, 0.99),
  trim_type = "value",
  ps_model = "mle",
  ridge_lambda = 1,
  outcome_fit = "separate"
)

Arguments

data

A data frame.

treatment

Name of the binary treatment column.

outcome

Name of the outcome column.

covariates

Character vector of covariate names.

group_col

Name of the grouping column.

propensity_col

Optional name of a column holding pre-computed propensity scores; NULL (default) estimates them within each group. Both routes are available.

trim

Propensity trimming bounds, or NULL for none.

trim_type

"value" (default) clamps the propensity scores to the absolute bounds trim; "quantile" winsorises them at their own sample quantiles. Both are weight truncation and keep every unit; neither is the DISCARD rule of Crump et al. (2009), which changes the estimand. The value route is the default here precisely because sample quantiles are unstable inside small strata, which is the situation this estimator creates. The Python arm takes the same two arguments with the same defaults.

ps_model

Propensity estimator: "mle" (default, unpenalised logistic maximum likelihood on the raw covariates) or "ridge" (L2-penalised logistic on standardised covariates). Both estimators are available on both arms.

ridge_lambda

Penalty strength for ps_model = "ridge".

outcome_fit

"separate" (default) fits the outcome model on each treatment arm; "pooled" fits one regression with a treatment dummy. Both routes are available on both arms.

Value

A data frame with one row per estimated group and columns group, ate, se, ci_lower, ci_upper, n.

References

Robins, J. M., Rotnitzky, A. and Zhao, L. P. (1994). Estimation of regression coefficients when some regressors are not always observed. JASA, 89(427), 846-866.

Examples

set.seed(14)
n <- 600
d <- data.frame(x = rnorm(n), g = sample(c("a", "b"), n, TRUE))
d$t <- rbinom(n, 1, plogis(d$x))
d$y <- 1 + d$t * ifelse(d$g == "a", 1, 2) + d$x + rnorm(n)
morie_gate(d, "t", "y", "x", group_col = "g")[, c("group", "ate", "se")]
#>   group       ate        se
#> 1     a 0.9186966 0.1140162
#> 2     b 2.0107588 0.1467464