Source code for moderndid.drdid.bootstrap.boot_mult

"""Standard multiplier bootstrap using Mammen weights."""

import numpy as np

from moderndid.core.numba_utils import multiplier_bootstrap as _multiplier_bootstrap


[docs] def mboot_did( linrep, n_bootstrap=1000, random_state=None, ): r"""Compute multiplier bootstrap for doubly robust DiD estimator using Mammen weights. Implements the standard multiplier bootstrap for computing doubly robust difference-in-differences estimates using Mammen's (1993) binary weights. It takes the influence function and applies bootstrap weights to compute bootstrap estimates. Parameters ---------- linrep : ndarray Influence function of shape (n_units,). n_bootstrap : int, default=1000 Number of bootstrap iterations. random_state : int | np.random.Generator | None, default=None Controls random number generation for reproducibility. Returns ------- ndarray Bootstrap estimates of shape (n_bootstrap,). References ---------- .. [1] Mammen, E. (1993). "Bootstrap and wild bootstrap for high dimensional linear models". The Annals of Statistics, 21(1), 255-285. """ linrep = np.asarray(linrep, dtype=np.float64).flatten() result = _multiplier_bootstrap(linrep, n_bootstrap, random_state) return result[:, 0]
[docs] def mboot_twfep_did( linrep, n_units, n_bootstrap=1000, random_state=None, ): r"""Compute multiplier bootstrap for TWFE panel data DiD using Mammen weights. Implements the standard multiplier bootstrap for Two-Way Fixed Effects difference-in-differences with panel data (2 periods and 2 groups) using Mammen's (1993) binary weights. Parameters ---------- linrep : ndarray Influence function values, stacked as [pre-period, post-period]. n_units : int Number of cross-sectional units. n_bootstrap : int, default=1000 Number of bootstrap iterations. random_state : int | np.random.Generator | None, default=None Controls random number generation for reproducibility. Returns ------- ndarray Bootstrap ATT estimates of shape (n_bootstrap,). References ---------- .. [1] Mammen, E. (1993). "Bootstrap and wild bootstrap for high dimensional linear models". The Annals of Statistics, 21(1), 255-285. Notes ----- The weights are generated at the unit level and then duplicated across time periods to maintain the panel structure. """ sqrt5 = np.sqrt(5) k1 = 0.5 * (1 - sqrt5) k2 = 0.5 * (1 + sqrt5) pkappa = 0.5 * (1 + sqrt5) / sqrt5 rng = np.random.default_rng(random_state) bootstrap_estimates = np.zeros(n_bootstrap) for b in range(n_bootstrap): v = rng.binomial(1, pkappa, size=n_units) v = np.where(v == 1, k1, k2) v = np.concatenate([v, v]) bootstrap_estimates[b] = np.mean(linrep * v) return bootstrap_estimates