From 9c086935ea5401560681ad43d242db3959fa8ebf Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Sat, 11 Apr 2026 15:19:33 -0400 Subject: [PATCH 01/12] builder: implement edid() -- Efficient DiD estimator (no-covariate path) Adds 14 new R source files implementing the Chen, Sant'Anna & Xie (2025) Efficient DiD estimator for staggered-adoption balanced panels. Key features: - PT-All and PT-Post regimes via enumerate_valid_pairs_edid() - Omega* covariance matrix and optimal inverse-covariance weights - Cluster-robust SE via EIF sandwich formula - Multiplier bootstrap (Rademacher, Mammen, Webb) - WIF correction in overall/event-study/group aggregations - edid_fit S3 class with print/summary/coef/vcov/as.data.frame methods - Covariate and survey paths are clean stubs (stop with message) - No new package dependencies (svd() replaces MASS::ginv) Co-Authored-By: Claude Sonnet 4.6 --- NAMESPACE | 8 + R/edid-aggregate.R | 450 +++++++++++++++++++ R/edid-bootstrap.R | 225 ++++++++++ R/edid-covariates.R | 51 +++ R/edid-data.R | 188 ++++++++ R/edid-fit.R | 170 +++++++ R/edid-imports.R | 11 + R/edid-inference.R | 88 ++++ R/edid-linalg.R | 74 +++ R/edid-methods.R | 294 ++++++++++++ R/edid-nocov.R | 355 +++++++++++++++ R/edid-pairs.R | 76 ++++ R/edid-utils.R | 43 ++ R/edid-validate.R | 248 ++++++++++ R/edid.R | 342 ++++++++++++++ man/aggregate_event_study_edid.Rd | 40 ++ man/aggregate_group_edid.Rd | 31 ++ man/aggregate_overall_edid.Rd | 29 ++ man/as.data.frame.edid_fit.Rd | 22 + man/build_cluster_index.Rd | 24 + man/check_condition_edid.Rd | 19 + man/cluster_aggregate_edid.Rd | 22 + man/coef.edid_fit.Rd | 22 + man/compute_bootstrap_stats_edid.Rd | 23 + man/compute_efficient_weights_edid.Rd | 19 + man/compute_eif_nocov_edid.Rd | 38 ++ man/compute_eif_se_edid.Rd | 20 + man/compute_generated_outcomes_nocov_edid.Rd | 32 ++ man/compute_omega_star_nocov_edid.Rd | 33 ++ man/compute_pseudoinverse_edid.Rd | 21 + man/compute_wif_contribution_edid.Rd | 41 ++ man/cov_nn_edid.Rd | 20 + man/edid.Rd | 158 +++++++ man/enumerate_valid_pairs_edid.Rd | 50 +++ man/fit_edid_cells.Rd | 43 ++ man/generate_multiplier_weights_edid.Rd | 36 ++ man/prepare_edid_panel.Rd | 45 ++ man/print.edid_fit.Rd | 19 + man/run_multiplier_bootstrap_edid.Rd | 52 +++ man/safe_inference_edid.Rd | 28 ++ man/safe_mean_edid.Rd | 18 + man/solve_ols_edid.Rd | 24 + man/summary.edid_fit.Rd | 20 + man/validate_edid_inputs.Rd | 58 +++ man/vcov.edid_fit.Rd | 24 + 45 files changed, 3654 insertions(+) create mode 100644 R/edid-aggregate.R create mode 100644 R/edid-bootstrap.R create mode 100644 R/edid-covariates.R create mode 100644 R/edid-data.R create mode 100644 R/edid-fit.R create mode 100644 R/edid-imports.R create mode 100644 R/edid-inference.R create mode 100644 R/edid-linalg.R create mode 100644 R/edid-methods.R create mode 100644 R/edid-nocov.R create mode 100644 R/edid-pairs.R create mode 100644 R/edid-utils.R create mode 100644 R/edid-validate.R create mode 100644 R/edid.R create mode 100644 man/aggregate_event_study_edid.Rd create mode 100644 man/aggregate_group_edid.Rd create mode 100644 man/aggregate_overall_edid.Rd create mode 100644 man/as.data.frame.edid_fit.Rd create mode 100644 man/build_cluster_index.Rd create mode 100644 man/check_condition_edid.Rd create mode 100644 man/cluster_aggregate_edid.Rd create mode 100644 man/coef.edid_fit.Rd create mode 100644 man/compute_bootstrap_stats_edid.Rd create mode 100644 man/compute_efficient_weights_edid.Rd create mode 100644 man/compute_eif_nocov_edid.Rd create mode 100644 man/compute_eif_se_edid.Rd create mode 100644 man/compute_generated_outcomes_nocov_edid.Rd create mode 100644 man/compute_omega_star_nocov_edid.Rd create mode 100644 man/compute_pseudoinverse_edid.Rd create mode 100644 man/compute_wif_contribution_edid.Rd create mode 100644 man/cov_nn_edid.Rd create mode 100644 man/edid.Rd create mode 100644 man/enumerate_valid_pairs_edid.Rd create mode 100644 man/fit_edid_cells.Rd create mode 100644 man/generate_multiplier_weights_edid.Rd create mode 100644 man/prepare_edid_panel.Rd create mode 100644 man/print.edid_fit.Rd create mode 100644 man/run_multiplier_bootstrap_edid.Rd create mode 100644 man/safe_inference_edid.Rd create mode 100644 man/safe_mean_edid.Rd create mode 100644 man/solve_ols_edid.Rd create mode 100644 man/summary.edid_fit.Rd create mode 100644 man/validate_edid_inputs.Rd create mode 100644 man/vcov.edid_fit.Rd diff --git a/NAMESPACE b/NAMESPACE index 969f75f..4da7c52 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,7 @@ # Generated by roxygen2: do not edit by hand +S3method(as.data.frame,edid_fit) +S3method(coef,edid_fit) S3method(ggdid,AGGTEobj) S3method(ggdid,MP) S3method(glance,AGGTEobj) @@ -8,11 +10,14 @@ S3method(nobs,AGGTEobj) S3method(nobs,MP) S3method(print,AGGTEobj) S3method(print,MP) +S3method(print,edid_fit) S3method(summary,AGGTEobj) S3method(summary,MP) S3method(summary,MP.TEST) +S3method(summary,edid_fit) S3method(tidy,AGGTEobj) S3method(tidy,MP) +S3method(vcov,edid_fit) export(AGGTEobj) export(DIDparams) export(MP) @@ -24,6 +29,7 @@ export(compute.aggte) export(compute.att_gt) export(compute.att_gt2) export(conditional_did_pretest) +export(edid) export(ggdid) export(glance) export(gplot) @@ -59,6 +65,7 @@ importFrom(generics,tidy) importFrom(methods,as) importFrom(methods,is) importFrom(stats,aggregate) +importFrom(stats,as.formula) importFrom(stats,binomial) importFrom(stats,complete.cases) importFrom(stats,cov) @@ -74,6 +81,7 @@ importFrom(stats,predict) importFrom(stats,qnorm) importFrom(stats,quantile) importFrom(stats,rnorm) +importFrom(stats,sd) importFrom(stats,setNames) importFrom(stats,var) importFrom(tidyr,gather) diff --git a/R/edid-aggregate.R b/R/edid-aggregate.R new file mode 100644 index 0000000..6b55201 --- /dev/null +++ b/R/edid-aggregate.R @@ -0,0 +1,450 @@ +# edid-aggregate.R +# Aggregation functions for the EDiD estimator: +# aggregate_overall_edid() +# aggregate_event_study_edid() +# aggregate_group_edid() +# compute_wif_contribution_edid() + +# --------------------------------------------------------------------------- +# Internal helper: pull EIF column from eif_matrix for a given cell_id +# --------------------------------------------------------------------------- +.eif_col <- function(eif_matrix, cell_id) { + if (is.null(eif_matrix)) return(NULL) + eif_matrix[, cell_id, drop = TRUE] +} + +# --------------------------------------------------------------------------- +# WIF correction +# --------------------------------------------------------------------------- + +#' Compute WIF (weight influence function) correction for aggregated EIF +#' +#' Corrects the aggregated EIF for estimation error in the cohort-share weights +#' \eqn{\pi_g = n_g / n}. The correction accounts for the fact that \eqn{\pi_g} +#' is estimated from data and therefore contributes to the variance of the +#' aggregated estimator. +#' +#' @param weight_fn function(cells, cell_index, panel_obj) that returns a named +#' numeric vector of normalized weights \eqn{q_k} for all post-treatment cells; +#' names are cell_ids (character) +#' @param cells list of \code{edid_cell_result} objects +#' @param eif_matrix n x n_cells numeric matrix (or NULL) +#' @param cell_index data.frame with columns \code{group}, \code{time}, +#' \code{cell_id}, \code{is_pre} +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param agg_att scalar: the already-computed aggregated ATT (used for WIF) +#' +#' @return numeric vector length n: WIF correction to add to aggregated EIF +#' @keywords internal +compute_wif_contribution_edid <- function( + weight_fn, cells, eif_matrix, cell_index, panel_obj, agg_att +) { + n <- panel_obj$n + wif <- numeric(n) + + if (is.null(eif_matrix)) return(wif) + + # Obtain normalized weights for all post-treatment cells + q_vec <- weight_fn(cells, cell_index, panel_obj) # named numeric + + # Get post-treatment cell ids and their ATTs + post_ci <- cell_index[!cell_index$is_pre, , drop = FALSE] + post_ids <- as.character(post_ci$cell_id) + post_atts <- vapply(post_ids, function(cid) { + idx <- which(post_ci$cell_id == as.integer(cid)) + cells[[post_ci$cell_id[idx]]]$att + }, numeric(1L)) + + # For each cohort g, compute the WIF contribution from pi_g uncertainty. + # WIF_i = sum_k [ (att_k - agg_att) * d(q_k)/d(pi_g_k) * d(pi_g_k)/dI(G_i=g_k) ] + # With q_k = pi_{g_k} / sum_{k'} pi_{g_{k'}} : + # d(q_k)/d(pi_g) = (I(g_k==g) * S - pi_{g_k}) / S^2 + # where S = sum_{k' in post} pi_{g_{k'}} + # d(pi_g)/dI(G_i=g) = (1/n) * (1 - I(G_i=g) * n_g_hat / n_g) ... simplified below + + S <- sum(q_vec[post_ids] * (q_vec[post_ids] > 0)) # sum of unnormalized weights + # Actually q_vec already gives normalized weights. Rebuild unnorm (pi_g_k): + # unnorm_k = pi_{g_k}; norm_k = pi_{g_k} / S_unnorm + # We need: d(q_k_norm)/d(pi_{g}) = (I(g_k==g)*S_u - pi_{g_k}) / S_u^2 + # where S_u = sum pi_{g_{k'}}. + + # Collect pi_{g_k} for each post cell + pi_by_cell <- vapply(post_ids, function(cid) { + g_val <- post_ci$group[post_ci$cell_id == as.integer(cid)] + panel_obj$cohort_fractions[[as.character(g_val)]] + }, numeric(1L)) + S_u <- sum(pi_by_cell) # sum of unnormalized (cohort share) weights + + if (S_u < EDID_DENOM_EPS) return(wif) + + for (g in panel_obj$treatment_groups) { + mask_g <- panel_obj$cohort_masks[[as.character(g)]] + n_g <- sum(mask_g) + if (n_g == 0L) next + pi_g <- panel_obj$cohort_fractions[[as.character(g)]] + + # Cells belonging to cohort g (among post cells) + g_post_mask <- post_ci$group == g + if (!any(g_post_mask)) next + + # sum_{k: g_k=g} (att_k - agg_att) * (S_u - pi_g * K_g) / S_u^2 + # where K_g = number of post cells for cohort g + # More precisely, the partial derivative for cohort g: + # dq_k/d(pi_g) = (I(g_k==g)*S_u - pi_g * sum_all 1) / S_u^2 + # But S_u = sum_k pi_{g_k}, so d(S_u)/d(pi_g) = K_g (# cells with g_k=g) + K_g <- sum(g_post_mask) + g_ids <- post_ids[g_post_mask] + g_atts <- post_atts[g_post_mask] + + # For each post cell k: + # if g_k == g: dq_k/d(pi_g) = (S_u - pi_g * K_g) / S_u^2 + 0 ... simplified: + # dq_k/d(pi_g) = (I(g_k==g) * S_u - pi_g * K_g) / S_u^2 + # if g_k != g: dq_k/d(pi_g) = -pi_{g_k} * K_g / S_u^2 + # Then d(agg_att)/d(pi_g) = sum_k att_k * dq_k/d(pi_g) + # And WIF contribution for unit i in cohort g: + # d(agg_att)/d(pi_g) * d(pi_g)/d(I(G_i=g)) = d(agg_att)/d(pi_g) * (1 - pi_g * K_g / K_g?) ... + # d(pi_g)/d(I(G_i=g)) = 1/n (adding one unit to cohort g increases pi_g by 1/n) + + # Contribution from cells in cohort g (g_k == g): + d_agg_d_pig_from_g <- sum(g_atts) * (S_u - pi_g * K_g) / (S_u^2) + # Contribution from cells NOT in cohort g (g_k != g): + not_g_mask <- !g_post_mask + if (any(not_g_mask)) { + not_g_atts <- post_atts[not_g_mask] + not_g_pi <- pi_by_cell[not_g_mask] + d_agg_d_pig_from_notg <- sum(not_g_atts * (-not_g_pi * K_g) / (S_u^2)) + } else { + d_agg_d_pig_from_notg <- 0 + } + d_agg_d_pig <- d_agg_d_pig_from_g + d_agg_d_pig_from_notg + + # Units in cohort g: d(pi_g)/dI(G_i=g) = 1/n + wif[mask_g] <- wif[mask_g] + d_agg_d_pig * (1 / n) + + # Units outside cohort g also have a contribution via d(pi_g)/dI(G_i=g): + # d(pi_g)/dI(G_i=g) for i not in g = -pi_g / (n * (1 - pi_g))... but + # using the simpler sample-level: d(n_g/n)/dI(G_i not g) = 0 exactly. + # (Adding unit i outside cohort g does not change n_g.) So no contribution + # for units outside cohort g from this cohort's weight derivative. Correct. + } + + wif +} + +# --------------------------------------------------------------------------- +# Overall ATT aggregation +# --------------------------------------------------------------------------- + +#' Aggregate cell-level ATTs into an overall ATT +#' +#' Uses cohort-share weights \eqn{q_k = \pi_{g_k}} over post-treatment cells, +#' normalized to sum to 1. Includes WIF correction for estimated weights. +#' +#' @param cells list of \code{edid_cell_result} objects (ordered by cell_id) +#' @param eif_matrix n x n_cells numeric matrix (or NULL if EIF not stored) +#' @param cell_index data.frame with columns \code{group}, \code{time}, +#' \code{cell_id}, \code{is_pre} +#' @param panel_obj panel object +#' @param alpha significance level +#' +#' @return named list: \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +#' \code{t_stat}, \code{p_value}, \code{eif_agg} +#' @keywords internal +aggregate_overall_edid <- function(cells, eif_matrix, cell_index, panel_obj, alpha) { + + # Post-treatment cells only + post_ci <- cell_index[!cell_index$is_pre, , drop = FALSE] + post_ids <- post_ci$cell_id # integer indices into cells list + + # Filter to cells with valid (non-NA) ATT + valid_mask <- vapply(post_ids, function(cid) { + !is.null(cells[[cid]]$att) && is.finite(cells[[cid]]$att) + }, logical(1L)) + + if (!any(valid_mask)) { + return(list(att = NA_real_, se = NA_real_, ci_lower = NA_real_, + ci_upper = NA_real_, t_stat = NA_real_, p_value = NA_real_, + eif_agg = NULL)) + } + + post_ci_v <- post_ci[valid_mask, , drop = FALSE] + post_ids_v <- post_ci_v$cell_id + + # Cohort-share weights (unnormalized) + pi_g_k <- vapply(post_ids_v, function(cid) { + panel_obj$cohort_fractions[[as.character(post_ci_v$group[post_ci_v$cell_id == cid])]] + }, numeric(1L)) + S_u <- sum(pi_g_k) + if (S_u < EDID_DENOM_EPS) { + return(list(att = NA_real_, se = NA_real_, ci_lower = NA_real_, + ci_upper = NA_real_, t_stat = NA_real_, p_value = NA_real_, + eif_agg = NULL)) + } + q_norm <- pi_g_k / S_u + + # Point estimate + att_k <- vapply(post_ids_v, function(cid) cells[[cid]]$att, numeric(1L)) + overall_att <- sum(q_norm * att_k) + + # Aggregated EIF (direct contribution) + eif_agg <- NULL + if (!is.null(eif_matrix)) { + n <- panel_obj$n + eif_agg <- numeric(n) + for (ii in seq_along(post_ids_v)) { + cid <- post_ids_v[ii] + eif_c <- .eif_col(eif_matrix, cid) + if (!is.null(eif_c)) { + eif_agg <- eif_agg + q_norm[ii] * eif_c + } + } + + # WIF correction: weight function for overall ATT + weight_fn_overall <- function(cells_arg, cell_index_arg, panel_obj_arg) { + ci_post <- cell_index_arg[!cell_index_arg$is_pre, , drop = FALSE] + ids <- ci_post$cell_id + valid <- vapply(ids, function(cid) { + !is.null(cells_arg[[cid]]$att) && is.finite(cells_arg[[cid]]$att) + }, logical(1L)) + ids_v <- ids[valid] + ci_v <- ci_post[valid, , drop = FALSE] + pg <- vapply(ids_v, function(cid) { + panel_obj_arg$cohort_fractions[[as.character( + ci_v$group[ci_v$cell_id == cid])]] + }, numeric(1L)) + Su <- sum(pg) + if (Su < EDID_DENOM_EPS) { + return(stats::setNames(rep(0, length(ids_v)), as.character(ids_v))) + } + stats::setNames(pg / Su, as.character(ids_v)) + } + + wif <- compute_wif_contribution_edid( + weight_fn_overall, cells, eif_matrix, cell_index, panel_obj, overall_att + ) + eif_agg <- eif_agg + wif + } + + # SE and inference + inf_res <- safe_inference_edid( + eif_agg, panel_obj$cluster_indices, alpha, overall_att + ) + + list( + att = overall_att, + se = inf_res$se, + ci_lower = inf_res$ci_lower, + ci_upper = inf_res$ci_upper, + t_stat = inf_res$t_stat, + p_value = inf_res$p_value, + eif_agg = eif_agg + ) +} + +# --------------------------------------------------------------------------- +# Event-study aggregation +# --------------------------------------------------------------------------- + +#' Aggregate cell-level ATTs by relative time (event study) +#' +#' For each unique relative time \eqn{e = t - g}, computes the cohort-share- +#' weighted average ATT over all \code{(g, t)} cells with \eqn{t - g = e}. +#' Includes WIF correction. +#' +#' @param cells list of \code{edid_cell_result} objects +#' @param eif_matrix n x n_cells numeric matrix (or NULL) +#' @param cell_index data.frame with columns \code{group}, \code{time}, +#' \code{cell_id}, \code{is_pre} +#' @param panel_obj panel object +#' @param alpha significance level +#' @param balance_e integer or NULL: if not NULL, restrict to \code{[-balance_e, balance_e]} +#' +#' @return named list, one entry per unique relative time; each entry is a list +#' with \code{e}, \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +#' \code{t_stat}, \code{p_value}, \code{eif_agg} +#' @keywords internal +aggregate_event_study_edid <- function( + cells, eif_matrix, cell_index, panel_obj, alpha, balance_e = NULL +) { + # Compute relative times + cell_index$e <- cell_index$time - cell_index$group + + # Apply balance_e restriction + if (!is.null(balance_e)) { + cell_index <- cell_index[abs(cell_index$e) <= balance_e, , drop = FALSE] + } + + unique_e <- sort(unique(cell_index$e)) + result <- vector("list", length(unique_e)) + names(result) <- as.character(unique_e) + + n <- panel_obj$n + + for (ii in seq_along(unique_e)) { + e_val <- unique_e[ii] + e_mask <- cell_index$e == e_val + e_ci <- cell_index[e_mask, , drop = FALSE] + e_ids <- e_ci$cell_id + + # Valid cells + valid <- vapply(e_ids, function(cid) { + !is.null(cells[[cid]]$att) && is.finite(cells[[cid]]$att) + }, logical(1L)) + + na_entry <- list(e = e_val, att = NA_real_, se = NA_real_, + ci_lower = NA_real_, ci_upper = NA_real_, + t_stat = NA_real_, p_value = NA_real_, eif_agg = NULL) + if (!any(valid)) { + result[[ii]] <- na_entry + next + } + + e_ci_v <- e_ci[valid, , drop = FALSE] + e_ids_v <- e_ci_v$cell_id + + pi_g_k <- vapply(seq_along(e_ids_v), function(jj) { + panel_obj$cohort_fractions[[as.character(e_ci_v$group[jj])]] + }, numeric(1L)) + S_u <- sum(pi_g_k) + if (S_u < EDID_DENOM_EPS) { result[[ii]] <- na_entry; next } + q_norm <- pi_g_k / S_u + + att_k <- vapply(e_ids_v, function(cid) cells[[cid]]$att, numeric(1L)) + es_att <- sum(q_norm * att_k) + + eif_agg <- NULL + if (!is.null(eif_matrix)) { + eif_agg <- numeric(n) + for (jj in seq_along(e_ids_v)) { + cid <- e_ids_v[jj] + eif_c <- .eif_col(eif_matrix, cid) + if (!is.null(eif_c)) eif_agg <- eif_agg + q_norm[jj] * eif_c + } + + # Build a cell_index restricted to this e-group for WIF + # WIF weight function: cohort-share weights restricted to this e + e_cell_index_restricted <- cell_index + # Mark non-e cells as pre so weight_fn ignores them + e_cell_index_restricted$is_pre <- TRUE + e_cell_index_restricted$is_pre[e_mask] <- e_ci$is_pre + + weight_fn_e <- .make_weight_fn_es(e_val) + wif <- compute_wif_contribution_edid( + weight_fn_e, cells, eif_matrix, e_cell_index_restricted, panel_obj, es_att + ) + eif_agg <- eif_agg + wif + } + + inf_res <- safe_inference_edid(eif_agg, panel_obj$cluster_indices, alpha, es_att) + + result[[ii]] <- list( + e = e_val, + att = es_att, + se = inf_res$se, + ci_lower = inf_res$ci_lower, + ci_upper = inf_res$ci_upper, + t_stat = inf_res$t_stat, + p_value = inf_res$p_value, + eif_agg = eif_agg + ) + } + result +} + +# Helper: build weight function for event-study relative time e +.make_weight_fn_es <- function(e_val) { + force(e_val) + function(cells_arg, cell_index_arg, panel_obj_arg) { + ci <- cell_index_arg + ci$e_local <- ci$time - ci$group + e_mask_local <- ci$e_local == e_val & !ci$is_pre + ids_v <- ci$cell_id[e_mask_local] + valid <- vapply(ids_v, function(cid) { + !is.null(cells_arg[[cid]]$att) && is.finite(cells_arg[[cid]]$att) + }, logical(1L)) + ids_v <- ids_v[valid] + ci_v <- ci[e_mask_local, , drop = FALSE][valid, , drop = FALSE] + pg <- vapply(seq_along(ids_v), function(jj) { + panel_obj_arg$cohort_fractions[[as.character(ci_v$group[jj])]] + }, numeric(1L)) + Su <- sum(pg) + if (Su < EDID_DENOM_EPS) { + return(stats::setNames(rep(0, length(ids_v)), as.character(ids_v))) + } + stats::setNames(pg / Su, as.character(ids_v)) + } +} + +# --------------------------------------------------------------------------- +# Group aggregation +# --------------------------------------------------------------------------- + +#' Aggregate cell-level ATTs by treatment cohort +#' +#' For each cohort \code{g}, computes the equal-time-weighted average ATT over +#' all post-treatment cells \code{(g, t)} with \code{t >= g}. +#' Group aggregation uses equal weights so there is no WIF correction. +#' +#' @param cells list of \code{edid_cell_result} objects +#' @param eif_matrix n x n_cells numeric matrix (or NULL) +#' @param cell_index data.frame with columns \code{group}, \code{time}, +#' \code{cell_id}, \code{is_pre} +#' @param panel_obj panel object +#' @param alpha significance level +#' +#' @return named list, one entry per cohort; each entry is a list with +#' \code{group}, \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +#' \code{t_stat}, \code{p_value}, \code{eif_agg} +#' @keywords internal +aggregate_group_edid <- function(cells, eif_matrix, cell_index, panel_obj, alpha) { + + tgroups <- panel_obj$treatment_groups + result <- vector("list", length(tgroups)) + names(result) <- as.character(tgroups) + n <- panel_obj$n + + for (ii in seq_along(tgroups)) { + g_val <- tgroups[ii] + g_mask <- cell_index$group == g_val & !cell_index$is_pre + g_ci <- cell_index[g_mask, , drop = FALSE] + g_ids <- g_ci$cell_id + + na_entry <- list(group = g_val, att = NA_real_, se = NA_real_, + ci_lower = NA_real_, ci_upper = NA_real_, + t_stat = NA_real_, p_value = NA_real_, eif_agg = NULL) + + valid <- vapply(g_ids, function(cid) { + !is.null(cells[[cid]]$att) && is.finite(cells[[cid]]$att) + }, logical(1L)) + if (!any(valid)) { result[[ii]] <- na_entry; next } + + g_ids_v <- g_ids[valid] + m_g <- length(g_ids_v) + att_k <- vapply(g_ids_v, function(cid) cells[[cid]]$att, numeric(1L)) + group_att <- mean(att_k) # equal weights + + eif_agg <- NULL + if (!is.null(eif_matrix)) { + eif_agg <- numeric(n) + for (cid in g_ids_v) { + eif_c <- .eif_col(eif_matrix, cid) + if (!is.null(eif_c)) eif_agg <- eif_agg + eif_c / m_g + } + # Equal weights: no WIF correction needed (weights don't depend on pi_g) + } + + inf_res <- safe_inference_edid(eif_agg, panel_obj$cluster_indices, alpha, group_att) + + result[[ii]] <- list( + group = g_val, + att = group_att, + se = inf_res$se, + ci_lower = inf_res$ci_lower, + ci_upper = inf_res$ci_upper, + t_stat = inf_res$t_stat, + p_value = inf_res$p_value, + eif_agg = eif_agg + ) + } + result +} diff --git a/R/edid-bootstrap.R b/R/edid-bootstrap.R new file mode 100644 index 0000000..14ae0bd --- /dev/null +++ b/R/edid-bootstrap.R @@ -0,0 +1,225 @@ +# edid-bootstrap.R +# Multiplier bootstrap for the EDiD estimator. + +#' Run the multiplier bootstrap for EDiD estimates +#' +#' Generates \code{n_bootstrap} perturbed versions of all cell-level ATTs +#' by multiplying stored EIF vectors with multiplier weights, then re-aggregates +#' using the same fixed cohort-share weights. +#' +#' @param cells list of \code{edid_cell_result} objects +#' @param eif_matrix n x n_cells numeric matrix of stored EIFs +#' @param cell_index data.frame with columns \code{group}, \code{time}, +#' \code{cell_id}, \code{is_pre} +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param n_bootstrap positive integer number of bootstrap draws +#' @param bootstrap_weights character: \code{"rademacher"}, \code{"mammen"}, +#' or \code{"webb"} +#' @param seed integer seed or NULL +#' @param aggregate character: which aggregations to return +#' @param balance_e integer or NULL +#' @param alpha significance level +#' +#' @return list with elements \code{overall_draws}, \code{event_study_draws}, +#' \code{group_draws}, \code{n_bootstrap}, \code{weight_type}, \code{seed} +#' @keywords internal +run_multiplier_bootstrap_edid <- function( + cells, eif_matrix, cell_index, panel_obj, + n_bootstrap, bootstrap_weights = "rademacher", seed = NULL, + aggregate = "all", balance_e = NULL, alpha = 0.05 +) { + n <- panel_obj$n + + # Generate multiplier weights: n x n_bootstrap matrix + xi_mat <- generate_multiplier_weights_edid( + n = n, + n_bootstrap = n_bootstrap, + type = bootstrap_weights, + cluster_indices = panel_obj$cluster_indices, + seed = seed + ) + + # Post-treatment cell ids and their ATTs + post_ci <- cell_index[!cell_index$is_pre, , drop = FALSE] + post_ids <- post_ci$cell_id + valid_post <- vapply(post_ids, function(cid) { + !is.null(cells[[cid]]$att) && is.finite(cells[[cid]]$att) + }, logical(1L)) + post_ci_v <- post_ci[valid_post, , drop = FALSE] + post_ids_v <- post_ci_v$cell_id + + # Perturbed cell ATTs: ATT_b(g,t) = ATT_hat(g,t) + (1/n) * xi' * EIF + # Build perturbed ATT matrix: n_valid_post x n_bootstrap + att_hat_post <- vapply(post_ids_v, function(cid) cells[[cid]]$att, numeric(1L)) + eif_post <- eif_matrix[, post_ids_v, drop = FALSE] # n x n_valid_post + # perturbation: (1/n) * t(xi_mat) %*% eif_post -> n_bootstrap x n_valid_post + perturb_mat <- (1 / n) * t(xi_mat) %*% eif_post + att_boot_mat <- sweep(perturb_mat, 2, att_hat_post, `+`) + # att_boot_mat: n_bootstrap x n_valid_post + + # Cohort-share weights for overall + pi_g_k <- vapply(seq_along(post_ids_v), function(jj) { + panel_obj$cohort_fractions[[as.character(post_ci_v$group[jj])]] + }, numeric(1L)) + S_u <- sum(pi_g_k) + q_norm <- if (S_u > EDID_DENOM_EPS) pi_g_k / S_u else rep(1 / length(pi_g_k), length(pi_g_k)) + + # ----------------------------------------------------------------------- + # Overall bootstrap draws + # ----------------------------------------------------------------------- + overall_draws <- NULL + if (aggregate %in% c("all", "overall")) { + overall_draws <- drop(att_boot_mat %*% q_norm) # n_bootstrap vector + } + + # ----------------------------------------------------------------------- + # Event-study bootstrap draws + # ----------------------------------------------------------------------- + event_study_draws <- NULL + if (aggregate %in% c("all", "event_study")) { + cell_index_v <- cell_index[cell_index$cell_id %in% post_ids_v, , drop = FALSE] + cell_index_v$e <- cell_index_v$time - cell_index_v$group + if (!is.null(balance_e)) { + cell_index_v <- cell_index_v[abs(cell_index_v$e) <= balance_e, , drop = FALSE] + } + unique_e <- sort(unique(cell_index_v$e)) + event_study_draws <- vector("list", length(unique_e)) + names(event_study_draws) <- as.character(unique_e) + + for (ii in seq_along(unique_e)) { + e_val <- unique_e[ii] + e_mask <- cell_index_v$e == e_val + e_ids <- cell_index_v$cell_id[e_mask] + e_g <- cell_index_v$group[e_mask] + # map e_ids to column indices in att_boot_mat + col_idx <- match(e_ids, post_ids_v) + col_idx <- col_idx[!is.na(col_idx)] + if (length(col_idx) == 0L) next + e_pi <- pi_g_k[col_idx] + e_Su <- sum(e_pi) + if (e_Su < EDID_DENOM_EPS) next + e_q <- e_pi / e_Su + event_study_draws[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% e_q) + } + } + + # ----------------------------------------------------------------------- + # Group bootstrap draws + # ----------------------------------------------------------------------- + group_draws <- NULL + if (aggregate %in% c("all", "group")) { + tgroups <- panel_obj$treatment_groups + group_draws <- vector("list", length(tgroups)) + names(group_draws) <- as.character(tgroups) + + for (ii in seq_along(tgroups)) { + g_val <- tgroups[ii] + g_mask <- post_ci_v$group == g_val + g_ids <- post_ci_v$cell_id[g_mask] + col_idx <- match(g_ids, post_ids_v) + col_idx <- col_idx[!is.na(col_idx)] + if (length(col_idx) == 0L) next + m_g <- length(col_idx) + g_q <- rep(1 / m_g, m_g) + group_draws[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% g_q) + } + } + + list( + overall_draws = overall_draws, + event_study_draws = event_study_draws, + group_draws = group_draws, + n_bootstrap = n_bootstrap, + weight_type = bootstrap_weights, + seed = seed + ) +} + +#' Generate multiplier bootstrap weights +#' +#' Returns an \code{n x n_bootstrap} matrix of multiplier weights drawn from +#' the specified distribution. When \code{cluster_indices} is supplied, +#' weights are drawn at the cluster level (G x n_bootstrap) and then +#' expanded to unit level by repeating within cluster. +#' +#' @param n integer: number of units +#' @param n_bootstrap positive integer: number of bootstrap draws +#' @param type character: \code{"rademacher"} (default), \code{"mammen"}, +#' or \code{"webb"} +#' @param cluster_indices integer vector length n (values 1..G) or NULL +#' @param seed integer seed or NULL +#' +#' @return numeric matrix n x n_bootstrap +#' @keywords internal +generate_multiplier_weights_edid <- function( + n, n_bootstrap, type = "rademacher", cluster_indices = NULL, seed = NULL +) { + if (!is.null(seed)) set.seed(seed) + + # Determine draw size + if (!is.null(cluster_indices)) { + G <- length(unique(cluster_indices)) + draw_n <- G + } else { + G <- NULL + draw_n <- n + } + + xi_raw <- switch(type, + rademacher = { + matrix(sample(c(-1, 1), draw_n * n_bootstrap, replace = TRUE), + nrow = draw_n, ncol = n_bootstrap) + }, + mammen = { + p_pos <- (sqrt(5) + 1) / (2 * sqrt(5)) + p_neg <- 1 - p_pos + v_pos <- (sqrt(5) + 1) / 2 + v_neg <- -(sqrt(5) - 1) / 2 + raw <- matrix( + sample(c(v_neg, v_pos), draw_n * n_bootstrap, replace = TRUE, + prob = c(p_neg, p_pos)), + nrow = draw_n, ncol = n_bootstrap + ) + raw + }, + webb = { + webb_vals <- c(-sqrt(3/2), -1, -sqrt(1/2), sqrt(1/2), 1, sqrt(3/2)) + matrix( + sample(webb_vals, draw_n * n_bootstrap, replace = TRUE), + nrow = draw_n, ncol = n_bootstrap + ) + }, + stop(sprintf("Unknown bootstrap_weights type: \"%s\". ", + type), + "Choose one of \"rademacher\", \"mammen\", or \"webb\".") + ) + + # Expand cluster-level draws to unit level + if (!is.null(cluster_indices)) { + xi_unit <- xi_raw[cluster_indices, , drop = FALSE] + return(xi_unit) + } + xi_raw +} + +#' Compute bootstrap SE, CI, and p-value from a vector of bootstrap draws +#' +#' @param boot_draws numeric vector of length \code{n_bootstrap} +#' @param att_hat scalar point estimate +#' @param alpha significance level in (0, 1) +#' +#' @return named list: \code{se_boot}, \code{ci_lower}, \code{ci_upper}, +#' \code{p_value_boot} +#' @keywords internal +compute_bootstrap_stats_edid <- function(boot_draws, att_hat, alpha = 0.05) { + se_boot <- stats::sd(boot_draws - att_hat) + ci_lower <- unname(stats::quantile(boot_draws, alpha / 2)) + ci_upper <- unname(stats::quantile(boot_draws, 1 - alpha / 2)) + p_value <- mean(abs(boot_draws - att_hat) >= abs(att_hat)) + list( + se_boot = se_boot, + ci_lower = ci_lower, + ci_upper = ci_upper, + p_value_boot = p_value + ) +} diff --git a/R/edid-covariates.R b/R/edid-covariates.R new file mode 100644 index 0000000..7205918 --- /dev/null +++ b/R/edid-covariates.R @@ -0,0 +1,51 @@ +# edid-covariates.R +# STUB ONLY: covariate path for EDiD is not yet implemented. +# All functions in this file stop with a clear message. + +#' @keywords internal +estimate_outcome_regression_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +build_polynomial_sieve_basis_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +estimate_propensity_ratio_sieve_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +estimate_inverse_propensity_sieve_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +compute_generated_outcomes_cov_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +compute_omega_star_conditional_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +compute_per_unit_weights_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} + +#' @keywords internal +compute_eif_cov_edid <- function(...) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") +} diff --git a/R/edid-data.R b/R/edid-data.R new file mode 100644 index 0000000..8b634d4 --- /dev/null +++ b/R/edid-data.R @@ -0,0 +1,188 @@ +# edid-data.R +# Panel preparation and cluster indexing for the EDiD estimator. + +#' Prepare the panel object used throughout edid estimation +#' +#' Reshapes the long-format input \code{data} into a wide outcome matrix and +#' builds all masks and maps needed by downstream functions. +#' +#' @param data data.frame (or data.table / tibble) already validated +#' @param outcome character scalar: outcome column name +#' @param unit character scalar: unit id column name +#' @param time character scalar: time column name +#' @param first_treat character scalar: first-treatment-period column name +#' @param covariates NULL (stub) +#' @param cluster character scalar or NULL +#' @param control_group \code{"never_treated"} or \code{"last_cohort"} +#' @param anticipation non-negative integer +#' +#' @return a \code{panel_obj} list; see spec Section 5.1 +#' @keywords internal +prepare_edid_panel <- function( + data, outcome, unit, time, first_treat, + covariates = NULL, cluster = NULL, + control_group = "never_treated", + anticipation = 0L +) { + + # ----------------------------------------------------------------------- + # 1. Coerce to data.table and sort + # ----------------------------------------------------------------------- + dt <- data.table::as.data.table(data) + data.table::setkeyv(dt, c(unit, time)) + + # ----------------------------------------------------------------------- + # 2-3. Extract sorted unique ids and time periods + # ----------------------------------------------------------------------- + all_units <- sort(unique(dt[[unit]])) + time_periods <- sort(unique(dt[[time]])) + n <- length(all_units) + T_periods <- length(time_periods) + + # ----------------------------------------------------------------------- + # 4. period_1 and period_to_col map + # ----------------------------------------------------------------------- + period_1 <- time_periods[1L] + period_to_col <- stats::setNames( + seq_along(time_periods), + as.character(time_periods) + ) + + # ----------------------------------------------------------------------- + # 5. Pivot to wide outcome matrix (n x T_periods) + # Rows correspond to all_units (sorted), columns to time_periods (sorted) + # ----------------------------------------------------------------------- + wide_dt <- data.table::dcast( + dt, + formula = stats::as.formula(paste(unit, "~ ", time)), + value.var = outcome + ) + # Ensure rows in same order as all_units + setattr <- function(x, nm, val) { attr(x, nm) <- val; x } + unit_order <- match(all_units, wide_dt[[unit]]) + wide_dt <- wide_dt[unit_order, ] + + # Drop the unit id column; keep only the T_periods outcome columns + # Column names after dcast are as.character(time_periods) + col_order <- as.character(time_periods) + outcome_wide <- as.matrix(wide_dt[, col_order, with = FALSE]) + rownames(outcome_wide) <- NULL + colnames(outcome_wide) <- col_order + + # ----------------------------------------------------------------------- + # 6. unit_cohorts: first_treat value per unit (Inf for never-treated) + # ----------------------------------------------------------------------- + # Extract one first_treat per unit using base R tapply (avoids data.table NSE) + ft_vals <- dt[[first_treat]] + unit_id_vals <- dt[[unit]] + # Get first value of first_treat per unit (treatment is constant within unit) + unit_ft_map <- tapply(ft_vals, unit_id_vals, function(x) x[1L]) + # Map to all_units order + unit_cohorts <- as.numeric(unit_ft_map[match(all_units, names(unit_ft_map))]) + + # ----------------------------------------------------------------------- + # 7. Handle last_cohort control group + # ----------------------------------------------------------------------- + if (control_group == "last_cohort") { + finite_cohorts <- unit_cohorts[is.finite(unit_cohorts)] + last_g <- max(finite_cohorts) + # Relabel last cohort as Inf (never-treated for estimation purposes) + unit_cohorts[unit_cohorts == last_g] <- Inf + # Trim time periods >= last_g + keep_times <- time_periods[time_periods < last_g] + keep_cols <- as.character(keep_times) + outcome_wide <- outcome_wide[, keep_cols, drop = FALSE] + time_periods <- keep_times + T_periods <- length(time_periods) + period_1 <- time_periods[1L] + period_to_col <- stats::setNames( + seq_along(time_periods), + as.character(time_periods) + ) + } + + # ----------------------------------------------------------------------- + # 8. treatment_groups: sorted unique finite cohort values + # ----------------------------------------------------------------------- + treatment_groups <- sort(unique(unit_cohorts[is.finite(unit_cohorts)])) + + # ----------------------------------------------------------------------- + # 9. cohort_masks: named list, one logical vector per cohort + # ----------------------------------------------------------------------- + cohort_masks <- vector("list", length(treatment_groups)) + names(cohort_masks) <- as.character(treatment_groups) + for (g_val in treatment_groups) { + cohort_masks[[as.character(g_val)]] <- (unit_cohorts == g_val) + } + + # ----------------------------------------------------------------------- + # 10. never_treated_mask + # ----------------------------------------------------------------------- + never_treated_mask <- is.infinite(unit_cohorts) + + # ----------------------------------------------------------------------- + # 11. cohort_fractions: pi_g = n_g / n + # ----------------------------------------------------------------------- + cohort_fractions <- stats::setNames( + vapply(treatment_groups, function(g_val) sum(unit_cohorts == g_val) / n, + numeric(1L)), + as.character(treatment_groups) + ) + + # ----------------------------------------------------------------------- + # 12. Clustering + # ----------------------------------------------------------------------- + cluster_indices <- NULL + n_clusters <- NULL + if (!is.null(cluster)) { + cluster_indices <- build_cluster_index(dt, unit, cluster, all_units) + n_clusters <- length(unique(cluster_indices)) + } + + # ----------------------------------------------------------------------- + # Assemble panel_obj + # ----------------------------------------------------------------------- + panel_obj <- list( + n = n, + T_periods = T_periods, + outcome_wide = outcome_wide, + time_periods = time_periods, + period_1 = period_1, + period_to_col = period_to_col, + all_units = all_units, + unit_cohorts = unit_cohorts, + treatment_groups = treatment_groups, + cohort_masks = cohort_masks, + never_treated_mask = never_treated_mask, + cohort_fractions = cohort_fractions, + cluster_indices = cluster_indices, + n_clusters = n_clusters, + covariate_matrix = NULL, # deferred + control_group = control_group, + anticipation = as.integer(anticipation) + ) + + panel_obj +} + +#' Build cluster integer index from cluster id column +#' +#' @param dt data.table (long format), sorted by unit then time +#' @param unit character scalar: unit id column name +#' @param cluster character scalar: cluster id column name +#' @param all_units sorted vector of unique unit ids +#' +#' @return integer vector length n (values 1..G) +#' @keywords internal +build_cluster_index <- function(dt, unit, cluster, all_units) { + # Extract time-invariant cluster id per unit using base R tapply + cl_vals <- dt[[cluster]] + unit_id_vals <- dt[[unit]] + cl_map <- tapply(cl_vals, unit_id_vals, function(x) x[1L]) + cl_ids <- cl_map[match(all_units, names(cl_map))] + + # Map cluster id -> integer index + sorted_cl <- sort(unique(cl_ids)) + cl_index <- match(cl_ids, sorted_cl) + cl_index +} diff --git a/R/edid-fit.R b/R/edid-fit.R new file mode 100644 index 0000000..2dab85c --- /dev/null +++ b/R/edid-fit.R @@ -0,0 +1,170 @@ +# edid-fit.R +# Outer (g, t) cell loop for the EDiD estimator. + +#' Fit all (g, t) cells for the EDiD estimator +#' +#' Iterates over all treatment cohorts and all time periods (excluding +#' \code{period_1}), computes point estimates, EIFs, and analytical SEs for +#' each cell. +#' +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param pt_assumption character: \code{"all"} or \code{"post"} +#' @param alpha significance level in (0, 1) +#' @param store_eif logical: if TRUE, include EIF vectors in returned cells +#' @param covariates NULL (covariate path is a stub) +#' @param need_eif logical: if TRUE, always store EIF regardless of store_eif +#' (used internally when \code{n_bootstrap > 0}) +#' +#' @return list with elements: +#' \describe{ +#' \item{\code{cells}}{list of \code{edid_cell_result} objects} +#' \item{\code{eif_matrix}}{n x n_valid_cells numeric matrix, or NULL} +#' \item{\code{cell_index}}{data.frame: group, time, cell_id, is_pre} +#' } +#' @keywords internal +fit_edid_cells <- function( + panel_obj, pt_assumption, alpha, store_eif, covariates, + need_eif = FALSE +) { + if (!is.null(covariates)) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") + } + + tgroups <- panel_obj$treatment_groups + tperiods <- panel_obj$time_periods + period_1 <- panel_obj$period_1 + n <- panel_obj$n + + # Periods to iterate over: all except period_1 + iter_periods <- tperiods[tperiods != period_1] + + # Pre-allocate cell list + n_cells <- length(tgroups) * length(iter_periods) + cells <- vector("list", n_cells) + + # cell_index tracking + ci_group <- numeric(n_cells) + ci_time <- numeric(n_cells) + ci_cell_id <- integer(n_cells) + ci_is_pre <- logical(n_cells) + + keep_eif <- store_eif || need_eif + eif_list <- if (keep_eif) vector("list", n_cells) else NULL + + cell_id <- 0L + + for (g in tgroups) { + for (t in iter_periods) { + cell_id <- cell_id + 1L + is_pre <- (t < g) + + # Step 1: enumerate valid pairs + pairs <- enumerate_valid_pairs_edid( + target_g = g, + treatment_groups = tgroups, + time_periods = tperiods, + period_1 = period_1, + pt_assumption = pt_assumption, + anticipation = panel_obj$anticipation + ) + + # NA cell if no valid pairs + if (nrow(pairs) == 0L) { + cells[[cell_id]] <- list( + group = g, + time = t, + att = NA_real_, + se = NA_real_, + ci_lower = NA_real_, + ci_upper = NA_real_, + t_stat = NA_real_, + p_value = NA_real_, + n_pairs = 0L, + weights = NULL, + condition_num = NA_real_, + is_pre = is_pre, + inference_valid = FALSE, + eif = NULL + ) + ci_group[cell_id] <- g + ci_time[cell_id] <- t + ci_cell_id[cell_id] <- cell_id + ci_is_pre[cell_id] <- is_pre + if (keep_eif) eif_list[[cell_id]] <- rep(NA_real_, n) + next + } + + # Step 2: generated outcomes + y_hat <- compute_generated_outcomes_nocov_edid(g, t, pairs, panel_obj, pt_assumption) + + # Step 3: Omega* + omega <- compute_omega_star_nocov_edid(g, t, pairs, panel_obj, pt_assumption) + + # Condition number diagnostics + cond_num <- tryCatch(check_condition_edid(omega), error = function(e) NA_real_) + + # Step 4: efficient weights + weights <- compute_efficient_weights_edid(omega) + + # Step 5: point estimate + att_gt <- sum(weights * y_hat) + + # Step 6: EIF + eif_gt <- compute_eif_nocov_edid(g, t, pairs, weights, panel_obj, att_gt, pt_assumption) + + # Step 7: SE and inference + inf_res <- safe_inference_edid(eif_gt, panel_obj$cluster_indices, alpha, att_gt) + + # Step 8: store + eif_store <- if (keep_eif) eif_gt else NULL + cells[[cell_id]] <- list( + group = g, + time = t, + att = att_gt, + se = inf_res$se, + ci_lower = inf_res$ci_lower, + ci_upper = inf_res$ci_upper, + t_stat = inf_res$t_stat, + p_value = inf_res$p_value, + n_pairs = nrow(pairs), + weights = weights, + condition_num = cond_num, + is_pre = is_pre, + inference_valid = inf_res$inference_valid, + eif = eif_store + ) + + ci_group[cell_id] <- g + ci_time[cell_id] <- t + ci_cell_id[cell_id] <- cell_id + ci_is_pre[cell_id] <- is_pre + + if (keep_eif) eif_list[[cell_id]] <- eif_gt + } + } + + # Build EIF matrix if needed + eif_matrix <- NULL + if (keep_eif) { + # Stack EIF vectors as columns: n x n_cells matrix + eif_matrix <- do.call(cbind, eif_list) + if (is.null(dim(eif_matrix))) { + eif_matrix <- matrix(eif_matrix, nrow = n) + } + } + + cell_index <- data.frame( + group = ci_group, + time = ci_time, + cell_id = ci_cell_id, + is_pre = ci_is_pre, + stringsAsFactors = FALSE + ) + + list( + cells = cells, + eif_matrix = eif_matrix, + cell_index = cell_index + ) +} diff --git a/R/edid-imports.R b/R/edid-imports.R new file mode 100644 index 0000000..29f7d35 --- /dev/null +++ b/R/edid-imports.R @@ -0,0 +1,11 @@ +# edid-imports.R +# @importFrom declarations for symbols used in edid-*.R files that are not +# already declared in imports.R. +# +# Note: stats::pnorm, stats::qnorm, stats::quantile, stats::sd, stats::setNames +# are already declared in imports.R. We add only symbols NOT already present. +# data.table is @imported (not just @importFrom) in imports.R, so dcast is +# available without an additional entry, but we add explicit entries for clarity. + +#' @importFrom stats sd quantile as.formula +NULL diff --git a/R/edid-inference.R b/R/edid-inference.R new file mode 100644 index 0000000..abe1823 --- /dev/null +++ b/R/edid-inference.R @@ -0,0 +1,88 @@ +# edid-inference.R +# Analytical standard error and inference helpers for the EDiD estimator. + +#' Safely compute SE, CI, and p-value from an EIF vector +#' +#' Dispatches to \code{compute_eif_se_edid()} with optional cluster aggregation. +#' If the resulting SE is not valid (zero, NA, or non-finite), all inference +#' results are set to \code{NA}. +#' +#' @param eif numeric vector length n (or NULL, for NA cells) +#' @param cluster_indices integer vector length n (1..G) or NULL +#' @param alpha significance level in (0, 1) +#' @param att scalar ATT estimate (used for t-stat; may be NA for inference check) +#' +#' @return named list: +#' \code{se}, \code{ci_lower}, \code{ci_upper}, \code{t_stat}, +#' \code{p_value}, \code{inference_valid} +#' @keywords internal +safe_inference_edid <- function(eif, cluster_indices = NULL, alpha = 0.05, + att = NA_real_) { + na_result <- list( + se = NA_real_, + ci_lower = NA_real_, + ci_upper = NA_real_, + t_stat = NA_real_, + p_value = NA_real_, + inference_valid = FALSE + ) + + if (is.null(eif) || !is.numeric(eif) || length(eif) == 0L) { + return(na_result) + } + + if (is.null(cluster_indices)) { + n <- length(eif) + se <- compute_eif_se_edid(eif, n) + } else { + G <- length(unique(cluster_indices)) + cluster_sums <- drop(rowsum(eif, cluster_indices)) + se <- sqrt((G / (G - 1)) * sum(cluster_sums^2) / (length(eif)^2)) + } + + valid <- is.finite(se) && se > EDID_SE_EPS + + if (!valid) return(na_result) + + z_crit <- qnorm(1 - alpha / 2) + t_stat <- if (is.finite(att)) att / se else NA_real_ + p_value <- if (is.finite(t_stat)) 2 * pnorm(-abs(t_stat)) else NA_real_ + + list( + se = se, + ci_lower = if (is.finite(att)) att - z_crit * se else NA_real_, + ci_upper = if (is.finite(att)) att + z_crit * se else NA_real_, + t_stat = t_stat, + p_value = p_value, + inference_valid = TRUE + ) +} + +#' Compute SE from EIF vector +#' +#' \deqn{SE = \sqrt{\sum_i \text{eif}_i^2 / n^2}} +#' +#' @param eif_vec numeric vector (may be cluster-aggregated sums) +#' @param n integer denominator (number of units or clusters) +#' +#' @return scalar SE +#' @keywords internal +compute_eif_se_edid <- function(eif_vec, n) { + sqrt(sum(eif_vec^2) / (n^2)) +} + +#' Aggregate EIF to cluster level (centered) +#' +#' Returns the vector of cluster sums of \code{eif}, mean-subtracted. +#' The small-sample correction \eqn{G/(G-1)} is applied in the SE formula +#' (in \code{safe_inference_edid}), not here. +#' +#' @param eif numeric vector length n +#' @param cluster_indices integer vector length n (values 1..G) +#' +#' @return numeric vector length G (cluster sums, centered) +#' @keywords internal +cluster_aggregate_edid <- function(eif, cluster_indices) { + cluster_sums <- drop(rowsum(eif, cluster_indices)) # length G + cluster_sums - mean(cluster_sums) +} diff --git a/R/edid-linalg.R b/R/edid-linalg.R new file mode 100644 index 0000000..cfa2309 --- /dev/null +++ b/R/edid-linalg.R @@ -0,0 +1,74 @@ +# edid-linalg.R +# Linear algebra helpers for the EDiD estimator. +# Uses base R svd() for pseudoinverse -- no MASS dependency. + +#' SVD-based Moore-Penrose pseudoinverse +#' +#' @param mat numeric matrix +#' @param tol tolerance for zero singular values; defaults to +#' \code{max(dim(mat)) * max(svd$d) * .Machine$double.eps} +#' @return matrix of same dimensions as \code{t(mat)} +#' @keywords internal +compute_pseudoinverse_edid <- function(mat, tol = NULL) { + s <- svd(mat) + d <- s$d + if (is.null(tol)) { + tol <- max(dim(mat)) * max(c(d, 0)) * .Machine$double.eps + } + # Zero out singular values below tolerance + d_inv <- ifelse(d > tol, 1 / d, 0) + # Pseudoinverse: V diag(d_inv) U' + s$v %*% diag(d_inv, nrow = length(d_inv)) %*% t(s$u) +} + +#' Condition number of a matrix via SVD +#' +#' @param mat numeric matrix +#' @return scalar: max singular value / min positive singular value. +#' Returns \code{Inf} if min singular value is 0. +#' @keywords internal +check_condition_edid <- function(mat) { + d <- svd(mat, nu = 0L, nv = 0L)$d + if (length(d) == 0L || max(d) == 0) return(Inf) + min_pos <- min(d[d > 0]) + if (length(min_pos) == 0L) return(Inf) + max(d) / min_pos +} + +#' Weighted OLS helper +#' +#' Computes \eqn{\hat\beta = (X'WX)^{-1} X'Wy} using \code{.lm.fit()}. +#' Falls back to SVD-based pseudoinverse if the normal equations are +#' numerically singular. +#' +#' @param X numeric matrix (n x p) +#' @param y numeric vector length n +#' @param weights numeric vector length n (NULL = uniform) +#' @return named list with elements \code{coef}, \code{fitted}, \code{residuals} +#' @keywords internal +solve_ols_edid <- function(X, y, weights = NULL) { + n <- nrow(X) + if (is.null(weights)) { + weights <- rep(1, n) + } + W <- sqrt(weights) + Xw <- X * W + yw <- y * W + fit <- tryCatch( + .lm.fit(Xw, yw), + error = function(e) NULL + ) + if (!is.null(fit) && all(is.finite(fit$coefficients))) { + beta <- fit$coefficients + yhat <- drop(X %*% beta) + resid <- y - yhat + return(list(coef = beta, fitted = yhat, residuals = resid)) + } + # Fallback: pseudoinverse + XtWX <- t(Xw) %*% Xw + XtWy <- t(Xw) %*% yw + beta <- drop(compute_pseudoinverse_edid(XtWX) %*% XtWy) + yhat <- drop(X %*% beta) + resid <- y - yhat + list(coef = beta, fitted = yhat, residuals = resid) +} diff --git a/R/edid-methods.R b/R/edid-methods.R new file mode 100644 index 0000000..c3b42c0 --- /dev/null +++ b/R/edid-methods.R @@ -0,0 +1,294 @@ +# edid-methods.R +# S3 methods for the edid_fit class. + +#' Print method for edid_fit objects +#' +#' Calls \code{summary.edid_fit()} and returns the object invisibly. +#' +#' @param x an \code{edid_fit} object +#' @param ... additional arguments (currently ignored) +#' +#' @return \code{x} invisibly +#' @export +print.edid_fit <- function(x, ...) { + summary(x, ...) + invisible(x) +} + +#' Summary method for edid_fit objects +#' +#' Prints a structured summary of the EDiD estimation results including +#' metadata, the cell-level ATT table, and aggregated estimates. +#' +#' @param object an \code{edid_fit} object +#' @param ... additional arguments (currently ignored) +#' +#' @return \code{object} invisibly +#' @export +summary.edid_fit <- function(object, ...) { + cat("\n=== Efficient Difference-in-Differences (EDiD) ===\n\n") + + # Metadata + cat(sprintf("PT assumption : %s\n", object$pt_assumption)) + cat(sprintf("Control group : %s\n", object$control_group)) + cat(sprintf("Anticipation : %d\n", object$anticipation)) + cat(sprintf("Units (n) : %d\n", object$n)) + cat(sprintf("Time periods (T) : %d\n", object$T_periods)) + cat(sprintf("Treatment cohorts : %s\n", + paste(object$treatment_groups, collapse = ", "))) + cat(sprintf("Inference type : %s\n", object$inference_type)) + if (!is.null(object$cluster)) { + cat(sprintf("Cluster variable : %s\n", object$cluster)) + } + cat(sprintf("Significance (alpha): %.3f\n\n", object$alpha)) + + # Cell-level ATT table (compact) + cat("--- Cell-level ATT(g, t) ---\n") + if (!is.null(object$att_gt) && nrow(object$att_gt) > 0L) { + att_print <- object$att_gt + att_print$pre <- ifelse(att_print$is_pre, "pre", "post") + # Round numeric columns for display + fmt_num <- function(x) ifelse(is.na(x), "NA", sprintf("%.4f", x)) + out <- data.frame( + group = att_print$group, + time = att_print$time, + type = att_print$pre, + att = fmt_num(att_print$att), + se = fmt_num(att_print$se), + ci_lower = fmt_num(att_print$ci_lower), + ci_upper = fmt_num(att_print$ci_upper), + p_value = fmt_num(att_print$p_value), + stringsAsFactors = FALSE + ) + print(out, row.names = FALSE, quote = FALSE) + } else { + cat(" (no cells)\n") + } + + # Overall ATT + if (!is.null(object$overall)) { + cat("\n--- Overall ATT ---\n") + ov <- object$overall + cat(sprintf(" ATT = %.4f SE = %s CI = [%s, %s] p = %s\n", + ov$att, + .fmt_or_na(ov$se), + .fmt_or_na(ov$ci_lower), + .fmt_or_na(ov$ci_upper), + .fmt_or_na(ov$p_value))) + } + + # Event-study + if (!is.null(object$event_study) && length(object$event_study) > 0L) { + cat("\n--- Event-Study ATT(e) ---\n") + for (es in object$event_study) { + cat(sprintf(" e = %3g: ATT = %.4f SE = %s p = %s\n", + es$e, + es$att, + .fmt_or_na(es$se), + .fmt_or_na(es$p_value))) + } + } + + # Group + if (!is.null(object$group) && length(object$group) > 0L) { + cat("\n--- Group ATT(g) ---\n") + for (gr in object$group) { + cat(sprintf(" g = %g: ATT = %.4f SE = %s p = %s\n", + gr$group, + gr$att, + .fmt_or_na(gr$se), + .fmt_or_na(gr$p_value))) + } + } + + cat("\n") + invisible(object) +} + +# Internal formatting helper +.fmt_or_na <- function(x) { + if (is.null(x) || !is.finite(x)) "NA" else sprintf("%.4f", x) +} + +#' Extract ATT coefficients from an edid_fit object +#' +#' @param object an \code{edid_fit} object +#' @param which character: one of \code{"att_gt"}, \code{"overall"}, +#' \code{"event_study"}, \code{"group"} +#' @param ... additional arguments (ignored) +#' +#' @return named numeric vector of ATT estimates +#' @export +coef.edid_fit <- function( + object, + which = c("att_gt", "overall", "event_study", "group"), + ... +) { + which <- match.arg(which) + switch(which, + att_gt = { + df <- object$att_gt + nms <- paste0("ATT(", df$group, ",", df$time, ")") + stats::setNames(df$att, nms) + }, + overall = { + c(overall = object$overall$att) + }, + event_study = { + vals <- vapply(object$event_study, function(x) x$att, numeric(1L)) + es <- object$event_study + nms <- vapply(es, function(x) paste0("e=", x$e), character(1L)) + stats::setNames(vals, nms) + }, + group = { + vals <- vapply(object$group, function(x) x$att, numeric(1L)) + nms <- vapply(object$group, function(x) paste0("g=", x$group), character(1L)) + stats::setNames(vals, nms) + } + ) +} + +#' Extract variance-covariance matrix from an edid_fit object +#' +#' Returns the outer product of aggregated EIF vectors, scaled by \eqn{1/n^2}. +#' When bootstrap inference is used, returns a diagonal matrix of bootstrap +#' variance estimates. +#' +#' @param object an \code{edid_fit} object +#' @param which character: one of \code{"att_gt"}, \code{"overall"}, +#' \code{"event_study"}, \code{"group"} +#' @param ... additional arguments (ignored) +#' +#' @return square numeric matrix +#' @export +vcov.edid_fit <- function( + object, + which = c("att_gt", "overall", "event_study", "group"), + ... +) { + which <- match.arg(which) + n <- object$n + + if (which == "overall") { + eif_v <- object$overall$eif_agg + if (is.null(eif_v)) return(matrix(NA_real_, 1L, 1L)) + return(matrix(sum(eif_v^2) / n^2, nrow = 1L, ncol = 1L, + dimnames = list("overall", "overall"))) + } + + if (which == "event_study") { + es_list <- object$event_study + if (is.null(es_list) || length(es_list) == 0L) return(matrix(NA_real_, 0L, 0L)) + nms <- vapply(es_list, function(x) paste0("e=", x$e), character(1L)) + K <- length(es_list) + vcv <- matrix(NA_real_, K, K, dimnames = list(nms, nms)) + for (j in seq_len(K)) { + eif_j <- es_list[[j]]$eif_agg + if (is.null(eif_j)) next + for (k in seq_len(K)) { + eif_k <- es_list[[k]]$eif_agg + if (is.null(eif_k)) next + vcv[j, k] <- sum(eif_j * eif_k) / n^2 + } + } + return(vcv) + } + + if (which == "group") { + gr_list <- object$group + if (is.null(gr_list) || length(gr_list) == 0L) return(matrix(NA_real_, 0L, 0L)) + nms <- vapply(gr_list, function(x) paste0("g=", x$group), character(1L)) + K <- length(gr_list) + vcv <- matrix(NA_real_, K, K, dimnames = list(nms, nms)) + for (j in seq_len(K)) { + eif_j <- gr_list[[j]]$eif_agg + if (is.null(eif_j)) next + for (k in seq_len(K)) { + eif_k <- gr_list[[k]]$eif_agg + if (is.null(eif_k)) next + vcv[j, k] <- sum(eif_j * eif_k) / n^2 + } + } + return(vcv) + } + + # att_gt: use cell-level EIFs from eif_matrix if available + if (!is.null(object$eif)) { + eif_mat <- object$eif + K <- ncol(eif_mat) + vcv <- (t(eif_mat) %*% eif_mat) / n^2 + df <- object$att_gt + nms <- paste0("ATT(", df$group, ",", df$time, ")") + dimnames(vcv) <- list(nms, nms) + return(vcv) + } + # Fallback: diagonal from stored SEs + df <- object$att_gt + nms <- paste0("ATT(", df$group, ",", df$time, ")") + K <- nrow(df) + vcv <- diag(df$se^2, nrow = K) + dimnames(vcv) <- list(nms, nms) + vcv +} + +#' Coerce edid_fit to a data.frame +#' +#' @param x an \code{edid_fit} object +#' @param which character: one of \code{"att_gt"}, \code{"overall"}, +#' \code{"event_study"}, \code{"group"} +#' @param ... additional arguments (ignored) +#' +#' @return data.frame +#' @export +as.data.frame.edid_fit <- function( + x, + which = c("att_gt", "overall", "event_study", "group"), + ... +) { + which <- match.arg(which) + switch(which, + att_gt = { + x$att_gt + }, + overall = { + ov <- x$overall + data.frame( + att = ov$att, + se = ov$se, + ci_lower = ov$ci_lower, + ci_upper = ov$ci_upper, + t_stat = ov$t_stat, + p_value = ov$p_value, + stringsAsFactors = FALSE + ) + }, + event_study = { + es_list <- x$event_study + if (is.null(es_list) || length(es_list) == 0L) { + return(data.frame(e = numeric(0L), att = numeric(0L), se = numeric(0L), + ci_lower = numeric(0L), ci_upper = numeric(0L), + p_value = numeric(0L))) + } + do.call(rbind, lapply(es_list, function(es) { + data.frame(e = es$e, att = es$att, se = es$se, + ci_lower = es$ci_lower, ci_upper = es$ci_upper, + t_stat = es$t_stat, p_value = es$p_value, + stringsAsFactors = FALSE) + })) + }, + group = { + gr_list <- x$group + if (is.null(gr_list) || length(gr_list) == 0L) { + return(data.frame(group = numeric(0L), att = numeric(0L), se = numeric(0L), + ci_lower = numeric(0L), ci_upper = numeric(0L), + p_value = numeric(0L))) + } + do.call(rbind, lapply(gr_list, function(gr) { + data.frame(group = gr$group, att = gr$att, se = gr$se, + ci_lower = gr$ci_lower, ci_upper = gr$ci_upper, + t_stat = gr$t_stat, p_value = gr$p_value, + stringsAsFactors = FALSE) + })) + } + ) +} diff --git a/R/edid-nocov.R b/R/edid-nocov.R new file mode 100644 index 0000000..a3d9d6b --- /dev/null +++ b/R/edid-nocov.R @@ -0,0 +1,355 @@ +# edid-nocov.R +# No-covariate path for the EDiD estimator: +# compute_omega_star_nocov_edid() +# compute_efficient_weights_edid() +# compute_generated_outcomes_nocov_edid() +# compute_eif_nocov_edid() + +# --------------------------------------------------------------------------- +# Helper: get column index from panel_obj +# --------------------------------------------------------------------------- +.col <- function(panel_obj, period_val) { + panel_obj$period_to_col[[as.character(period_val)]] +} + +# --------------------------------------------------------------------------- +# Omega* covariance matrix (H x H) +# --------------------------------------------------------------------------- + +#' Compute the Omega* covariance matrix for the no-covariate EDiD path +#' +#' Builds the \eqn{H \times H} sample covariance matrix of the identifying +#' moments for cell \code{(target_g, target_t)}. +#' +#' @param target_g scalar cohort value +#' @param target_t scalar time period +#' @param pairs data.frame with columns \code{gp} and \code{tpre}; H rows +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param pt_assumption \code{"all"} or \code{"post"} +#' +#' @return numeric matrix H x H +#' @keywords internal +compute_omega_star_nocov_edid <- function( + target_g, target_t, pairs, panel_obj, pt_assumption +) { + H <- nrow(pairs) + n <- panel_obj$n + ow <- panel_obj$outcome_wide + + mask_g <- panel_obj$cohort_masks[[as.character(target_g)]] + mask_inf <- panel_obj$never_treated_mask + n_g <- sum(mask_g) + n_inf <- sum(mask_inf) + + col_t <- .col(panel_obj, target_t) + col_1 <- .col(panel_obj, panel_obj$period_1) + + if (pt_assumption == "post") { + # PT-Post: 1x1 matrix = var of standard DiD moment + tpre_val <- pairs$tpre[1L] + col_base <- .col(panel_obj, tpre_val) + + delta_g <- ow[mask_g, col_t] - ow[mask_g, col_base] + delta_inf <- ow[mask_inf, col_t] - ow[mask_inf, col_base] + + omega <- matrix( + cov_nn_edid(delta_g, delta_g) / n_g + + cov_nn_edid(delta_inf, delta_inf) / n_inf, + nrow = 1L, ncol = 1L + ) + return(omega) + } + + # --------------------------------------------------------------------------- + # PT-All: H x H matrix, entry-by-entry + # --------------------------------------------------------------------------- + # Pre-compute treated-group change (same for all j, k) + delta_g_t_1 <- ow[mask_g, col_t] - ow[mask_g, col_1] + + # Pre-compute never-treated changes for each unique tpre + unique_tpre <- unique(pairs$tpre) + delta_inf_cache <- vector("list", length(unique_tpre)) + names(delta_inf_cache) <- as.character(unique_tpre) + for (tp in unique_tpre) { + col_pre <- .col(panel_obj, tp) + delta_inf_cache[[as.character(tp)]] <- + ow[mask_inf, col_t] - ow[mask_inf, col_pre] + } + + # Pre-compute comparison-cohort changes for each unique (gp, tpre) + unique_gp_tpre <- unique(pairs[, c("gp", "tpre")]) + delta_gp_cache <- list() + for (rr in seq_len(nrow(unique_gp_tpre))) { + gp_val <- unique_gp_tpre$gp[rr] + tp_val <- unique_gp_tpre$tpre[rr] + key <- paste0(gp_val, "_", tp_val) + if (is.finite(gp_val)) { + mask_gp <- panel_obj$cohort_masks[[as.character(gp_val)]] + col_pre <- .col(panel_obj, tp_val) + delta_gp_cache[[key]] <- ow[mask_gp, col_pre] - ow[mask_gp, col_1] + } else { + # Never-treated: delta_{inf, tpre, 1} = Y_{tpre} - Y_{period_1} + col_pre <- .col(panel_obj, tp_val) + delta_gp_cache[[key]] <- ow[mask_inf, col_pre] - ow[mask_inf, col_1] + } + } + + omega <- matrix(0, nrow = H, ncol = H) + + for (j in seq_len(H)) { + gp_j <- pairs$gp[j] + tpre_j <- pairs$tpre[j] + key_j <- paste0(gp_j, "_", tpre_j) + n_gp_j <- if (is.finite(gp_j)) { + sum(panel_obj$cohort_masks[[as.character(gp_j)]]) + } else { + n_inf + } + delta_inf_j <- delta_inf_cache[[as.character(tpre_j)]] + delta_gp_j <- delta_gp_cache[[key_j]] + + for (k in seq_len(H)) { + if (k < j) { + omega[j, k] <- omega[k, j] # symmetric + next + } + gp_k <- pairs$gp[k] + tpre_k <- pairs$tpre[k] + key_k <- paste0(gp_k, "_", tpre_k) + n_gp_k <- if (is.finite(gp_k)) { + sum(panel_obj$cohort_masks[[as.character(gp_k)]]) + } else { + n_inf + } + delta_inf_k <- delta_inf_cache[[as.character(tpre_k)]] + delta_gp_k <- delta_gp_cache[[key_k]] + + # Term A: treated group variance (always present; same for all j, k) + term_a <- cov_nn_edid(delta_g_t_1, delta_g_t_1) / n_g + + # Term B: never-treated cross-covariance + term_b <- cov_nn_edid(delta_inf_j, delta_inf_k) / n_inf + + # Term C_j: non-zero only if gp_j == target_g + term_cj <- 0 + if (is.finite(gp_j) && gp_j == target_g) { + term_cj <- cov_nn_edid(delta_g_t_1, delta_gp_j) / n_g + } + + # Term C_k: non-zero only if gp_k == target_g + term_ck <- 0 + if (is.finite(gp_k) && gp_k == target_g) { + term_ck <- cov_nn_edid(delta_g_t_1, delta_gp_k) / n_g + } + + # Term D: non-zero only if gp_j == gp_k + term_d <- 0 + if (gp_j == gp_k) { # works for both finite and Inf + term_d <- cov_nn_edid(delta_gp_j, delta_gp_k) / n_gp_j + } + + omega[j, k] <- term_a + term_b - term_cj - term_ck + term_d + } + } + + omega +} + +# --------------------------------------------------------------------------- +# Efficient weights +# --------------------------------------------------------------------------- + +#' Compute efficient inverse-covariance weights +#' +#' Implements \eqn{w = (\Omega^{*-1} \mathbf{1}) / (\mathbf{1}' \Omega^{*-1} \mathbf{1})} +#' with fallback to uniform weights when the matrix is degenerate. +#' +#' @param omega_star numeric matrix H x H +#' +#' @return numeric vector length H, summing to 1 +#' @keywords internal +compute_efficient_weights_edid <- function(omega_star) { + H <- nrow(omega_star) + ones_H <- rep(1, H) + unif <- ones_H / H + + # Degenerate: all zeros -> uniform + if (all(omega_star == 0)) return(unif) + + # Check condition number + kappa <- check_condition_edid(omega_star) + if (!is.finite(kappa) || kappa > EDID_COND_THRESH) { + inv_omega <- compute_pseudoinverse_edid(omega_star) + } else { + inv_omega <- tryCatch( + solve(omega_star), + error = function(e) compute_pseudoinverse_edid(omega_star) + ) + } + + num <- drop(inv_omega %*% ones_H) + denom <- sum(num) + if (!is.finite(denom) || abs(denom) < EDID_DENOM_EPS) return(unif) + num / denom +} + +# --------------------------------------------------------------------------- +# Generated outcomes (scalar moments) +# --------------------------------------------------------------------------- + +#' Compute generated-outcome scalars for each valid pair +#' +#' @param target_g scalar cohort value +#' @param target_t scalar time period +#' @param pairs data.frame with columns \code{gp} and \code{tpre}; H rows +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param pt_assumption \code{"all"} or \code{"post"} +#' +#' @return numeric vector length H +#' @keywords internal +compute_generated_outcomes_nocov_edid <- function( + target_g, target_t, pairs, panel_obj, pt_assumption +) { + H <- nrow(pairs) + ow <- panel_obj$outcome_wide + + mask_g <- panel_obj$cohort_masks[[as.character(target_g)]] + mask_inf <- panel_obj$never_treated_mask + + col_t <- .col(panel_obj, target_t) + + if (pt_assumption == "post") { + # PT-Post: one pair (Inf, base) + tpre_val <- pairs$tpre[1L] + col_base <- .col(panel_obj, tpre_val) + y_hat <- mean(ow[mask_g, col_t] - ow[mask_g, col_base]) - + mean(ow[mask_inf, col_t] - ow[mask_inf, col_base]) + return(y_hat) # scalar; will be treated as length-1 vector + } + + # PT-All + col_1 <- .col(panel_obj, panel_obj$period_1) + term_g <- mean(ow[mask_g, col_t] - ow[mask_g, col_1]) + + y_hat <- numeric(H) + for (j in seq_len(H)) { + gp_j <- pairs$gp[j] + tpre_j <- pairs$tpre[j] + col_pre <- .col(panel_obj, tpre_j) + + term_inf <- mean(ow[mask_inf, col_t] - ow[mask_inf, col_pre]) + + if (is.finite(gp_j)) { + mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] + term_gp <- mean(ow[mask_gp, col_pre] - ow[mask_gp, col_1]) + } else { + # gp = Inf: comparison is never-treated baseline change + term_gp <- mean(ow[mask_inf, col_pre] - ow[mask_inf, col_1]) + } + + y_hat[j] <- term_g - term_inf - term_gp + } + y_hat +} + +# --------------------------------------------------------------------------- +# Efficient Influence Function (per unit, length n) +# --------------------------------------------------------------------------- + +#' Compute the no-covariate efficient influence function for a (g, t) cell +#' +#' @param target_g scalar cohort value +#' @param target_t scalar time period +#' @param pairs data.frame with columns \code{gp} and \code{tpre}; H rows +#' @param weights numeric vector length H (efficient weights) +#' @param panel_obj panel object from \code{prepare_edid_panel()} +#' @param att_gt scalar ATT estimate for this cell +#' @param pt_assumption \code{"all"} or \code{"post"} +#' +#' @return numeric vector length n (zero-mean by construction) +#' @keywords internal +compute_eif_nocov_edid <- function( + target_g, target_t, pairs, weights, panel_obj, att_gt, pt_assumption +) { + n <- panel_obj$n + H <- nrow(pairs) + ow <- panel_obj$outcome_wide + + mask_g <- panel_obj$cohort_masks[[as.character(target_g)]] + mask_inf <- panel_obj$never_treated_mask + pi_g <- panel_obj$cohort_fractions[[as.character(target_g)]] + pi_inf <- sum(mask_inf) / n + + col_t <- .col(panel_obj, target_t) + + eif <- numeric(n) + + if (pt_assumption == "post") { + # PT-Post: one pair; base = g - 1 - anticipation + tpre_val <- pairs$tpre[1L] + col_base <- .col(panel_obj, tpre_val) + w_1 <- weights[1L] + + delta_g <- ow[mask_g, col_t] - ow[mask_g, col_base] + mean_g <- mean(delta_g) + eif[mask_g] <- eif[mask_g] + w_1 * (delta_g - mean_g) / pi_g + + delta_inf <- ow[mask_inf, col_t] - ow[mask_inf, col_base] + mean_inf <- mean(delta_inf) + eif[mask_inf] <- eif[mask_inf] - w_1 * (delta_inf - mean_inf) / pi_inf + + # gp_j == Inf: no comparison cohort term + } else { + # PT-All + col_1 <- .col(panel_obj, panel_obj$period_1) + col_base <- col_1 # base for treated group + + delta_g_t_base <- ow[mask_g, col_t] - ow[mask_g, col_base] + mean_g_t_base <- mean(delta_g_t_base) + + for (j in seq_len(H)) { + w_j <- weights[j] + gp_j <- pairs$gp[j] + tpre_j <- pairs$tpre[j] + col_pre <- .col(panel_obj, tpre_j) + + # Treated group contribution (always present) + # Y_hat_j enters via centering: phi_{ij} = I(G=g)/pi_g * (delta - Y_hat_j) + # But the EIF is: score - att_gt, and score = sum w_j phi_{ij} + # phi_{ij} for treated group = I(G=g)/pi_g * (delta_{g,t,base} - Y_hat_j) + # We compute: sum_j w_j * I(G=g)/pi_g * (delta - Y_hat_j) + # = I(G=g)/pi_g * [ (delta - mean_g) + (mean_g - sum_j w_j Y_hat_j) ] + # But it's simpler to accumulate directly: + eif[mask_g] <- eif[mask_g] + + w_j * (delta_g_t_base - mean_g_t_base) / pi_g + + # Never-treated contribution (subtract) + delta_inf_t_pre <- ow[mask_inf, col_t] - ow[mask_inf, col_pre] + mean_inf_t_pre <- mean(delta_inf_t_pre) + eif[mask_inf] <- eif[mask_inf] - + w_j * (delta_inf_t_pre - mean_inf_t_pre) / pi_inf + + # Comparison cohort contribution (subtract, only if gp_j is finite) + if (is.finite(gp_j)) { + mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] + pi_gp <- panel_obj$cohort_fractions[[as.character(gp_j)]] + delta_gp_pre_base <- ow[mask_gp, col_pre] - ow[mask_gp, col_base] + mean_gp_pre_base <- mean(delta_gp_pre_base) + eif[mask_gp] <- eif[mask_gp] - + w_j * (delta_gp_pre_base - mean_gp_pre_base) / pi_gp + } + # If gp_j == Inf: the comparison cohort is never-treated itself, + # which contributes only through the -delta_inf term above. + # The baseline change delta_{inf, tpre, 1} contributes to the + # never-treated units with an additional term when gp_j==Inf in PT-All. + # Per the EIF formula: phi_{ij} for gp_j==Inf has no 3rd indicator + # term (since I(G_i=gp_j) == I(G_i=Inf) which is already handled + # in the never-treated contribution above when we subtract the mean). + # No additional action needed here. + } + } + + # Center: EIF = score - ATT_hat + eif <- eif - att_gt + eif +} diff --git a/R/edid-pairs.R b/R/edid-pairs.R new file mode 100644 index 0000000..bfa991d --- /dev/null +++ b/R/edid-pairs.R @@ -0,0 +1,76 @@ +# edid-pairs.R +# Enumerate the set of valid comparison pairs H_gt for a target cell (g, t). + +#' Enumerate valid comparison pairs for a target (g, t) cell +#' +#' Constructs the set \eqn{H_{gt}} of valid \code{(g', t_pre)} pairs used to +#' form identifying DiD moments for cohort \code{target_g} at time \code{target_t}. +#' +#' Under \strong{PT-Post}: returns exactly one pair \code{(Inf, target_g - 1 - anticipation)}, +#' or a 0-row data.frame if that pre-period does not exist in \code{time_periods} or +#' equals \code{period_1}. +#' +#' Under \strong{PT-All}: returns all \code{(gp, tpre)} pairs where \code{gp} ranges +#' over all cohorts (including never-treated) and \code{tpre} is a valid pre-period +#' strictly less than the effective treatment start of \code{gp}, excluding \code{period_1}. +#' +#' @param target_g scalar: treatment cohort being estimated +#' @param treatment_groups sorted numeric vector of all finite cohort values +#' @param time_periods sorted numeric vector of all time periods in the panel +#' @param period_1 scalar: universal first period +#' @param pt_assumption character: \code{"all"} or \code{"post"} +#' @param anticipation integer >= 0 +#' @param never_treated_val value used to represent the never-treated cohort +#' (default \code{Inf}) +#' +#' @return data.frame with columns \code{gp} (comparison cohort) and +#' \code{tpre} (pre-period). May have 0 rows. +#' @keywords internal +enumerate_valid_pairs_edid <- function( + target_g, + treatment_groups, + time_periods, + period_1, + pt_assumption, + anticipation = 0L, + never_treated_val = Inf +) { + empty <- data.frame(gp = numeric(0L), tpre = numeric(0L)) + + if (pt_assumption == "post") { + # ----------------------------------------------------------------------- + # PT-Post: exactly one pair (Inf, g - 1 - anticipation) + # ----------------------------------------------------------------------- + tpre_val <- target_g - 1L - anticipation + if (!tpre_val %in% time_periods) return(empty) + if (tpre_val == period_1) return(empty) + return(data.frame(gp = never_treated_val, tpre = tpre_val)) + } + + # ------------------------------------------------------------------------- + # PT-All: loop over all candidate comparison cohorts + # ------------------------------------------------------------------------- + candidate_gps <- c(treatment_groups, never_treated_val) + + out_gp <- numeric(0L) + out_tpre <- numeric(0L) + + for (gp in candidate_gps) { + if (is.finite(gp)) { + # Finite comparison cohort: effective treatment start = gp - anticipation + eff_start <- gp - anticipation + # Valid tpre: strictly less than eff_start, not period_1 + valid_tpre <- time_periods[time_periods < eff_start & time_periods != period_1] + } else { + # Never-treated: all periods except period_1 are valid + valid_tpre <- time_periods[time_periods != period_1] + } + if (length(valid_tpre) > 0L) { + out_gp <- c(out_gp, rep(gp, length(valid_tpre))) + out_tpre <- c(out_tpre, valid_tpre) + } + } + + if (length(out_gp) == 0L) return(empty) + data.frame(gp = out_gp, tpre = out_tpre, stringsAsFactors = FALSE) +} diff --git a/R/edid-utils.R b/R/edid-utils.R new file mode 100644 index 0000000..0bf0210 --- /dev/null +++ b/R/edid-utils.R @@ -0,0 +1,43 @@ +# edid-utils.R +# Internal constants and small shared helpers for the EDiD estimator. +# Do NOT modify this file to change the estimator logic -- see the relevant +# edid-*.R file for each component. + +#' @keywords internal +EDID_COND_THRESH <- 1e12 # condition number above which pseudoinverse is used + +#' @keywords internal +EDID_DENOM_EPS <- 1e-12 # denominator threshold below which uniform weights are used + +#' @keywords internal +EDID_CLIP_LO <- 1 / 20 # ratio clipping lower bound (deferred: covariate path) + +#' @keywords internal +EDID_CLIP_HI <- 20 # ratio clipping upper bound (deferred: covariate path) + +#' @keywords internal +EDID_SE_EPS <- sqrt(.Machine$double.eps) * 10 # SE below which is treated as zero/NA + +# --------------------------------------------------------------------------- +# Small shared helpers +# --------------------------------------------------------------------------- + +#' Biased sample covariance (divide by n, not n-1) +#' +#' @param x numeric vector +#' @param y numeric vector, same length as x +#' @return scalar +#' @keywords internal +cov_nn_edid <- function(x, y) { + mean((x - mean(x)) * (y - mean(y))) +} + +#' Safe mean: returns NA on empty vector instead of NaN +#' +#' @param x numeric vector +#' @return scalar +#' @keywords internal +safe_mean_edid <- function(x) { + if (length(x) == 0L) return(NA_real_) + mean(x) +} diff --git a/R/edid-validate.R b/R/edid-validate.R new file mode 100644 index 0000000..bb2709d --- /dev/null +++ b/R/edid-validate.R @@ -0,0 +1,248 @@ +# edid-validate.R +# Input validation for edid(). All checks are performed before any computation. + +#' Validate inputs to \code{edid()} +#' +#' Performs all structural and type checks on user-supplied arguments. +#' Returns invisibly \code{TRUE} on success; stops with an informative message +#' on any failure. +#' +#' @param data data.frame or coercible +#' @param outcome character scalar: outcome column name +#' @param unit character scalar: unit id column name +#' @param time character scalar: time column name +#' @param first_treat character scalar: first-treatment-period column name +#' @param covariates character vector or NULL +#' @param pt_assumption character scalar, already matched via \code{match.arg} +#' @param alpha numeric scalar in (0, 1) +#' @param cluster character scalar or NULL +#' @param control_group character scalar, already matched via \code{match.arg} +#' @param n_bootstrap non-negative integer +#' @param anticipation non-negative integer +#' @param survey_design always NULL (survey not yet implemented) +#' +#' @return invisibly TRUE +#' @keywords internal +validate_edid_inputs <- function( + data, outcome, unit, time, first_treat, covariates, + pt_assumption, alpha, cluster, control_group, + n_bootstrap, anticipation, survey_design +) { + + # ------------------------------------------------------------------ + # 1. data is data.frame-like and has rows + # ------------------------------------------------------------------ + if (!is.data.frame(data) && !inherits(data, "data.table") && + !inherits(data, "tbl_df")) { + # try coercing + tryCatch( + data <- as.data.frame(data), + error = function(e) stop("`data` must be a data.frame or coercible to one.") + ) + } + if (nrow(data) == 0L) { + stop("`data` has no rows.") + } + + # ------------------------------------------------------------------ + # 2. outcome / unit / time / first_treat are character scalars naming + # existing columns + # ------------------------------------------------------------------ + .check_col <- function(arg, argname) { + if (!is.character(arg) || length(arg) != 1L) { + stop(sprintf("`%s` must be a character scalar (column name).", argname)) + } + if (!arg %in% names(data)) { + stop(sprintf("`%s` = \"%s\" is not a column in `data`.", argname, arg)) + } + } + .check_col(outcome, "outcome") + .check_col(unit, "unit") + .check_col(time, "time") + .check_col(first_treat, "first_treat") + + # Columns must be distinct + col_names <- c(outcome, unit, time, first_treat) + if (anyDuplicated(col_names)) { + stop("`outcome`, `unit`, `time`, and `first_treat` must name distinct columns.") + } + + # ------------------------------------------------------------------ + # 3. outcome column is numeric; no NA; all finite + # ------------------------------------------------------------------ + y_col <- data[[outcome]] + if (!is.numeric(y_col)) { + stop(sprintf("Column `%s` (outcome) must be numeric.", outcome)) + } + if (anyNA(y_col)) { + stop(sprintf("Column `%s` (outcome) contains NA values. ", + outcome), + "edid() requires a complete, balanced panel with no missing outcomes.") + } + if (!all(is.finite(y_col))) { + stop(sprintf("Column `%s` (outcome) contains non-finite values (Inf/-Inf/NaN). ", + outcome), + "edid() requires all outcomes to be finite.") + } + + # ------------------------------------------------------------------ + # 4. time column is numeric; no NA + # ------------------------------------------------------------------ + t_col <- data[[time]] + if (!is.numeric(t_col)) { + stop(sprintf("Column `%s` (time) must be numeric.", time)) + } + if (anyNA(t_col)) { + stop(sprintf("Column `%s` (time) contains NA values.", time)) + } + + # ------------------------------------------------------------------ + # 5. first_treat column is numeric; no NA + # ------------------------------------------------------------------ + ft_col <- data[[first_treat]] + if (!is.numeric(ft_col)) { + stop(sprintf("Column `%s` (first_treat) must be numeric.", first_treat)) + } + if (anyNA(ft_col)) { + stop(sprintf("Column `%s` (first_treat) contains NA values. ", + first_treat), + "Use Inf to denote never-treated units.") + } + + # ------------------------------------------------------------------ + # 6. No duplicate (unit, time) rows + # ------------------------------------------------------------------ + ut_key <- paste(data[[unit]], data[[time]], sep = "___") + if (anyDuplicated(ut_key)) { + stop("Duplicate (unit, time) pairs found in `data`. ", + "edid() requires a balanced panel with exactly one observation per unit-period.") + } + + # ------------------------------------------------------------------ + # 7. Panel is balanced: every unit appears in every time period + # ------------------------------------------------------------------ + all_units_v <- unique(data[[unit]]) + all_times_v <- unique(data[[time]]) + n_units <- length(all_units_v) + n_times <- length(all_times_v) + expected_obs <- n_units * n_times + if (nrow(data) != expected_obs) { + stop(sprintf( + "Panel is unbalanced: expected %d rows (%d units x %d periods) but found %d. ", + expected_obs, n_units, n_times, nrow(data)), + "edid() requires a balanced panel.") + } + + # ------------------------------------------------------------------ + # 8. Treatment is absorbing: first_treat is constant within unit + # ------------------------------------------------------------------ + ft_by_unit <- tapply(data[[first_treat]], data[[unit]], function(x) length(unique(x))) + if (any(ft_by_unit > 1L)) { + bad <- names(ft_by_unit)[ft_by_unit > 1L] + stop(sprintf( + "`%s` (first_treat) is not constant within unit for %d unit(s) (e.g., %s). ", + first_treat, length(bad), bad[1]), + "Treatment must be absorbing.") + } + + # ------------------------------------------------------------------ + # 9-10. Control group availability + # ------------------------------------------------------------------ + # Get time-invariant first_treat per unit (one row per unit) + unit_ft <- tapply(data[[first_treat]], data[[unit]], `[`, 1L) + + if (control_group == "never_treated") { + n_never <- sum(is.infinite(unit_ft)) + if (n_never == 0L) { + stop("No never-treated units found (`first_treat == Inf`). ", + "edid() requires never-treated units when `control_group = \"never_treated\"`.") + } + } else { + # last_cohort + finite_ft <- unit_ft[is.finite(unit_ft)] + if (length(finite_ft) == 0L) { + stop("No finite first-treatment values found; cannot determine last cohort.") + } + last_g <- max(finite_ft) + n_last <- sum(finite_ft == last_g) + if (n_last == 0L) { + stop("No units in the last treated cohort found. ", + "Cannot use `control_group = \"last_cohort\"`.") + } + } + + # ------------------------------------------------------------------ + # 11. covariates != NULL -> stop (stub) + # ------------------------------------------------------------------ + if (!is.null(covariates)) { + stop("covariate path not yet implemented in edid(). ", + "Pass covariates = NULL or omit the covariates argument.") + } + + # ------------------------------------------------------------------ + # 12. survey_design != NULL -> stop (stub) + # ------------------------------------------------------------------ + if (!is.null(survey_design)) { + stop("survey_design not yet implemented in edid(). ", + "Pass survey_design = NULL or omit the argument.") + } + + # ------------------------------------------------------------------ + # 13. alpha in (0, 1) + # ------------------------------------------------------------------ + if (!is.numeric(alpha) || length(alpha) != 1L || alpha <= 0 || alpha >= 1) { + stop("`alpha` must be a numeric scalar strictly between 0 and 1.") + } + + # ------------------------------------------------------------------ + # 14. n_bootstrap >= 0 integer + # ------------------------------------------------------------------ + if (!is.numeric(n_bootstrap) || length(n_bootstrap) != 1L || + n_bootstrap < 0 || n_bootstrap != floor(n_bootstrap)) { + stop("`n_bootstrap` must be a non-negative integer.") + } + + # ------------------------------------------------------------------ + # 15. anticipation >= 0 integer; effective pre-treatment check + # ------------------------------------------------------------------ + if (!is.numeric(anticipation) || length(anticipation) != 1L || + anticipation < 0 || anticipation != floor(anticipation)) { + stop("`anticipation` must be a non-negative integer.") + } + min_ft <- min(unit_ft[is.finite(unit_ft)]) + min_t <- min(all_times_v) + if (min_ft - anticipation <= min_t) { + stop(sprintf( + "With `anticipation = %d`, the earliest treatment cohort (%g) would be treated at or before ", + anticipation, min_ft), + sprintf("the first observed period (%g). ", min_t), + "There must be at least one pre-treatment period available.") + } + + # ------------------------------------------------------------------ + # 16. cluster column checks + # ------------------------------------------------------------------ + if (!is.null(cluster)) { + if (!is.character(cluster) || length(cluster) != 1L) { + stop("`cluster` must be a character scalar naming a column in `data`, or NULL.") + } + if (!cluster %in% names(data)) { + stop(sprintf("`cluster` = \"%s\" is not a column in `data`.", cluster)) + } + cl_col <- data[[cluster]] + if (anyNA(cl_col)) { + stop(sprintf("Cluster column `%s` contains NA values.", cluster)) + } + # Time-invariant within unit + cl_by_unit <- tapply(cl_col, data[[unit]], function(x) length(unique(x))) + if (any(cl_by_unit > 1L)) { + bad <- names(cl_by_unit)[cl_by_unit > 1L] + stop(sprintf( + "Cluster variable `%s` is not time-invariant for %d unit(s) (e.g., %s). ", + cluster, length(bad), bad[1]), + "Cluster variable must be constant within unit.") + } + } + + invisible(TRUE) +} diff --git a/R/edid.R b/R/edid.R new file mode 100644 index 0000000..a558938 --- /dev/null +++ b/R/edid.R @@ -0,0 +1,342 @@ +#' Efficient Difference-in-Differences Estimator +#' +#' Estimates group-time average treatment effects \eqn{ATT(g, t)} for staggered +#' adoption designs using the Efficient DiD (EDiD) estimator of Chen, Sant'Anna +#' & Xie (2025). The estimator combines all valid DiD identifying moments for +#' each \eqn{(g, t)} cell with optimal inverse-covariance weights to achieve +#' minimum asymptotic variance. +#' +#' @param data A \code{data.frame}, \code{data.table}, or tibble in long format +#' (one row per unit-time observation). +#' @param outcome Character scalar: name of the outcome column (must be numeric +#' with no missing or non-finite values). +#' @param unit Character scalar: name of the unit identifier column. +#' @param time Character scalar: name of the time period column (numeric). +#' @param first_treat Character scalar: name of the column recording each unit's +#' first treatment period. Never-treated units should have \code{Inf} (or +#' \code{NA} is not accepted --- use \code{Inf} explicitly). +#' @param covariates Character vector of covariate column names, or \code{NULL} +#' (default). \strong{Currently not implemented}: passing non-NULL triggers an +#' error. +#' @param pt_assumption Parallel-trends assumption regime. One of: +#' \describe{ +#' \item{\code{"all"}}{PT-All: parallel trends holds for all pre-treatment +#' periods (default). Uses all valid \eqn{(g', t_{pre})} pairs.} +#' \item{\code{"post"}}{PT-Post: parallel trends holds only for the period +#' immediately before treatment. Each cell uses a single DiD moment.} +#' } +#' @param alpha Significance level for confidence intervals. Default \code{0.05}. +#' @param cluster Character scalar naming a time-invariant cluster variable in +#' \code{data}, or \code{NULL} for no clustering (default). When supplied, +#' cluster-robust standard errors are computed via the sandwich EIF formula. +#' @param control_group Control group definition. One of: +#' \describe{ +#' \item{\code{"never_treated"}}{Use never-treated units (default).} +#' \item{\code{"last_cohort"}}{Use the last-treated cohort as +#' pseudo-controls (relabeled as never-treated internally).} +#' } +#' @param n_bootstrap Non-negative integer: number of multiplier bootstrap draws. +#' \code{0} (default) returns analytical standard errors only. +#' @param bootstrap_weights Distribution for multiplier weights. One of +#' \code{"rademacher"} (default), \code{"mammen"}, or \code{"webb"}. +#' @param seed Integer seed for reproducibility of bootstrap draws, or +#' \code{NULL} (default, no seed set). +#' @param anticipation Non-negative integer: number of anticipation periods. +#' Default \code{0L}. The effective treatment start for cohort \eqn{g} is +#' \eqn{g - \text{anticipation}}. +#' @param aggregate Which aggregations to compute. One or more of +#' \code{"all"} (default), \code{"overall"}, \code{"event_study"}, +#' \code{"group"}, or \code{"none"}. +#' @param balance_e Integer or \code{NULL}: if not \code{NULL}, restricts the +#' event-study aggregation to relative times in +#' \eqn{[-\text{balance\_e}, \text{balance\_e}]}. +#' @param survey_design Always \code{NULL}. Survey designs are not yet +#' implemented; passing a non-NULL value triggers an error. +#' @param store_eif Logical: if \code{TRUE}, store the full \eqn{n \times K} +#' EIF matrix in \code{edid_fit$eif}. Default \code{FALSE}. The EIF is +#' always computed internally when \code{n_bootstrap > 0}. +#' +#' @return An object of class \code{edid_fit} (a list) with elements: +#' \describe{ +#' \item{\code{call}}{The matched call.} +#' \item{\code{att_gt}}{data.frame of cell-level estimates (group, time, +#' att, se, ci_lower, ci_upper, t_stat, p_value, is_pre).} +#' \item{\code{overall}}{List: overall ATT with SE and CI.} +#' \item{\code{event_study}}{List of per-relative-time ATTs.} +#' \item{\code{group}}{List of per-cohort ATTs.} +#' \item{\code{eif}}{EIF matrix or \code{NULL}.} +#' \item{\code{bootstrap}}{Bootstrap results or \code{NULL}.} +#' } +#' +#' @references Chen, L., Sant'Anna, P. H. C., & Xie, Y. (2025). +#' \emph{Efficient Difference-in-Differences}. Working paper. +#' +#' @examples +#' # Simulate a simple balanced panel with staggered adoption +#' set.seed(42) +#' n_units <- 100 +#' n_periods <- 6 +#' unit_ids <- rep(1:n_units, each = n_periods) +#' time_ids <- rep(1:n_periods, times = n_units) +#' # Assign cohorts: 1/3 treated in period 3, 1/3 in period 5, 1/3 never +#' cohort_assign <- rep( +#' c(3, 5, Inf), +#' times = c(ceiling(n_units / 3), +#' ceiling(n_units / 3), +#' n_units - 2 * ceiling(n_units / 3)) +#' )[1:n_units] +#' first_treat_vec <- cohort_assign[unit_ids] +#' # Generate outcomes: ATT = 1 for treated post-treatment +#' treat_effect <- as.numeric(time_ids >= first_treat_vec) +#' y_vals <- 0.5 * time_ids + treat_effect + rnorm(n_units * n_periods, sd = 0.5) +#' panel_df <- data.frame( +#' id = unit_ids, +#' period = time_ids, +#' y = y_vals, +#' first_treat = first_treat_vec +#' ) +#' # Fit EDiD (no-covariate, PT-All, analytical SE) +#' fit <- edid( +#' data = panel_df, +#' outcome = "y", +#' unit = "id", +#' time = "period", +#' first_treat = "first_treat", +#' pt_assumption = "all" +#' ) +#' # View overall ATT +#' fit$overall$att +#' # Extract cell-level estimates +#' head(fit$att_gt) +#' +#' @export +edid <- function( + data, + outcome, + unit, + time, + first_treat, + covariates = NULL, + pt_assumption = c("all", "post"), + alpha = 0.05, + cluster = NULL, + control_group = c("never_treated", "last_cohort"), + n_bootstrap = 0L, + bootstrap_weights = c("rademacher", "mammen", "webb"), + seed = NULL, + anticipation = 0L, + aggregate = c("all", "overall", "event_study", "group", "none"), + balance_e = NULL, + survey_design = NULL, + store_eif = FALSE +) { + mc <- match.call() + + # ------------------------------------------------------------------ + # Argument matching + # ------------------------------------------------------------------ + pt_assumption <- match.arg(pt_assumption) + control_group <- match.arg(control_group) + bootstrap_weights <- match.arg(bootstrap_weights) + aggregate <- match.arg(aggregate, several.ok = TRUE) + # When "all" is present it subsumes the others + if ("all" %in% aggregate) aggregate <- "all" + + n_bootstrap <- as.integer(n_bootstrap) + anticipation <- as.integer(anticipation) + + # ------------------------------------------------------------------ + # Validation + # ------------------------------------------------------------------ + validate_edid_inputs( + data = data, + outcome = outcome, + unit = unit, + time = time, + first_treat = first_treat, + covariates = covariates, + pt_assumption = pt_assumption, + alpha = alpha, + cluster = cluster, + control_group = control_group, + n_bootstrap = n_bootstrap, + anticipation = anticipation, + survey_design = survey_design + ) + + # ------------------------------------------------------------------ + # Panel preparation + # ------------------------------------------------------------------ + panel_obj <- prepare_edid_panel( + data = data, + outcome = outcome, + unit = unit, + time = time, + first_treat = first_treat, + covariates = covariates, + cluster = cluster, + control_group = control_group, + anticipation = anticipation + ) + + # ------------------------------------------------------------------ + # Cell estimation + # EIF is always needed for aggregated SE computation, not just bootstrap. + # ------------------------------------------------------------------ + do_any_agg <- !("none" %in% aggregate) + need_eif_for_boot <- (n_bootstrap > 0L) + # need_eif: TRUE whenever we need aggregated inference OR bootstrap + need_eif_internal <- do_any_agg || need_eif_for_boot + + fit_result <- fit_edid_cells( + panel_obj = panel_obj, + pt_assumption = pt_assumption, + alpha = alpha, + store_eif = store_eif, + covariates = covariates, + need_eif = need_eif_internal + ) + + cells <- fit_result$cells + eif_matrix <- fit_result$eif_matrix + cell_index <- fit_result$cell_index + + # ------------------------------------------------------------------ + # Convenience att_gt table + # ------------------------------------------------------------------ + att_gt_df <- data.frame( + group = vapply(cells, function(x) x$group, numeric(1L)), + time = vapply(cells, function(x) x$time, numeric(1L)), + att = vapply(cells, function(x) if (is.null(x$att)) NA_real_ else x$att, numeric(1L)), + se = vapply(cells, function(x) if (is.null(x$se)) NA_real_ else x$se, numeric(1L)), + ci_lower = vapply(cells, function(x) if (is.null(x$ci_lower)) NA_real_ else x$ci_lower, numeric(1L)), + ci_upper = vapply(cells, function(x) if (is.null(x$ci_upper)) NA_real_ else x$ci_upper, numeric(1L)), + t_stat = vapply(cells, function(x) if (is.null(x$t_stat)) NA_real_ else x$t_stat, numeric(1L)), + p_value = vapply(cells, function(x) if (is.null(x$p_value)) NA_real_ else x$p_value, numeric(1L)), + n_pairs = vapply(cells, function(x) if (is.null(x$n_pairs)) 0L else x$n_pairs, integer(1L)), + is_pre = vapply(cells, function(x) x$is_pre, logical(1L)), + stringsAsFactors = FALSE + ) + + # ------------------------------------------------------------------ + # Aggregation + # ------------------------------------------------------------------ + do_overall <- aggregate %in% c("all", "overall") + do_event_study <- aggregate %in% c("all", "event_study") + do_group <- aggregate %in% c("all", "group") + + overall_res <- NULL + event_study_res <- NULL + group_res <- NULL + + if (do_overall) { + overall_res <- aggregate_overall_edid(cells, eif_matrix, cell_index, panel_obj, alpha) + } + if (do_event_study) { + event_study_res <- aggregate_event_study_edid( + cells, eif_matrix, cell_index, panel_obj, alpha, balance_e + ) + } + if (do_group) { + group_res <- aggregate_group_edid(cells, eif_matrix, cell_index, panel_obj, alpha) + } + + # ------------------------------------------------------------------ + # Bootstrap + # ------------------------------------------------------------------ + bootstrap_res <- NULL + if (n_bootstrap > 0L) { + if (is.null(eif_matrix)) { + warning("EIF matrix is NULL; bootstrap cannot be run. ", + "This should not happen --- please report this issue.") + } else { + boot_agg <- if ("all" %in% aggregate || identical(aggregate, "all")) "all" else + paste(intersect(aggregate, c("overall", "event_study", "group")), collapse = ",") + bootstrap_res <- run_multiplier_bootstrap_edid( + cells = cells, + eif_matrix = eif_matrix, + cell_index = cell_index, + panel_obj = panel_obj, + n_bootstrap = n_bootstrap, + bootstrap_weights = bootstrap_weights, + seed = seed, + aggregate = "all", + balance_e = balance_e, + alpha = alpha + ) + class(bootstrap_res) <- c("edid_bootstrap", "list") + + # Overwrite SEs/CIs with bootstrap versions + if (do_overall && !is.null(overall_res) && !is.null(bootstrap_res$overall_draws)) { + bs_ov <- compute_bootstrap_stats_edid(bootstrap_res$overall_draws, overall_res$att, alpha) + overall_res$se <- bs_ov$se_boot + overall_res$ci_lower <- bs_ov$ci_lower + overall_res$ci_upper <- bs_ov$ci_upper + overall_res$p_value <- bs_ov$p_value_boot + overall_res$t_stat <- if (!is.na(bs_ov$se_boot) && bs_ov$se_boot > 0) { + overall_res$att / bs_ov$se_boot + } else NA_real_ + } + + if (do_event_study && !is.null(event_study_res) && + !is.null(bootstrap_res$event_study_draws)) { + for (e_nm in names(event_study_res)) { + draws <- bootstrap_res$event_study_draws[[e_nm]] + if (is.null(draws)) next + bs_es <- compute_bootstrap_stats_edid(draws, event_study_res[[e_nm]]$att, alpha) + event_study_res[[e_nm]]$se <- bs_es$se_boot + event_study_res[[e_nm]]$ci_lower <- bs_es$ci_lower + event_study_res[[e_nm]]$ci_upper <- bs_es$ci_upper + event_study_res[[e_nm]]$p_value <- bs_es$p_value_boot + } + } + + if (do_group && !is.null(group_res) && !is.null(bootstrap_res$group_draws)) { + for (g_nm in names(group_res)) { + draws <- bootstrap_res$group_draws[[g_nm]] + if (is.null(draws)) next + bs_gr <- compute_bootstrap_stats_edid(draws, group_res[[g_nm]]$att, alpha) + group_res[[g_nm]]$se <- bs_gr$se_boot + group_res[[g_nm]]$ci_lower <- bs_gr$ci_lower + group_res[[g_nm]]$ci_upper <- bs_gr$ci_upper + group_res[[g_nm]]$p_value <- bs_gr$p_value_boot + } + # Also update cell-level SEs from bootstrap if we have per-cell draws + # (not stored at cell level -- only aggregate-level bootstrap is implemented) + } + } + } + + # ------------------------------------------------------------------ + # EIF matrix storage (only if user requested it) + # ------------------------------------------------------------------ + eif_export <- if (store_eif) eif_matrix else NULL + + # ------------------------------------------------------------------ + # Construct edid_fit S3 object + # ------------------------------------------------------------------ + edid_fit <- list( + call = mc, + pt_assumption = pt_assumption, + control_group = control_group, + alpha = alpha, + n = panel_obj$n, + T_periods = panel_obj$T_periods, + treatment_groups = panel_obj$treatment_groups, + anticipation = panel_obj$anticipation, + inference_type = if (n_bootstrap > 0L) "bootstrap" else "analytical", + cluster = cluster, + cells = cells, + att_gt = att_gt_df, + overall = overall_res, + event_study = event_study_res, + group = group_res, + eif = eif_export, + bootstrap = bootstrap_res, + n_bootstrap = n_bootstrap, + bootstrap_weights = bootstrap_weights + ) + + class(edid_fit) <- c("edid_fit", "list") + edid_fit +} diff --git a/man/aggregate_event_study_edid.Rd b/man/aggregate_event_study_edid.Rd new file mode 100644 index 0000000..e893224 --- /dev/null +++ b/man/aggregate_event_study_edid.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggregate.R +\name{aggregate_event_study_edid} +\alias{aggregate_event_study_edid} +\title{Aggregate cell-level ATTs by relative time (event study)} +\usage{ +aggregate_event_study_edid( + cells, + eif_matrix, + cell_index, + panel_obj, + alpha, + balance_e = NULL +) +} +\arguments{ +\item{cells}{list of \code{edid_cell_result} objects} + +\item{eif_matrix}{n x n_cells numeric matrix (or NULL)} + +\item{cell_index}{data.frame with columns \code{group}, \code{time}, +\code{cell_id}, \code{is_pre}} + +\item{panel_obj}{panel object} + +\item{alpha}{significance level} + +\item{balance_e}{integer or NULL: if not NULL, restrict to \code{[-balance_e, balance_e]}} +} +\value{ +named list, one entry per unique relative time; each entry is a list +with \code{e}, \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +\code{t_stat}, \code{p_value}, \code{eif_agg} +} +\description{ +For each unique relative time \eqn{e = t - g}, computes the cohort-share- +weighted average ATT over all \code{(g, t)} cells with \eqn{t - g = e}. +Includes WIF correction. +} +\keyword{internal} diff --git a/man/aggregate_group_edid.Rd b/man/aggregate_group_edid.Rd new file mode 100644 index 0000000..0596831 --- /dev/null +++ b/man/aggregate_group_edid.Rd @@ -0,0 +1,31 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggregate.R +\name{aggregate_group_edid} +\alias{aggregate_group_edid} +\title{Aggregate cell-level ATTs by treatment cohort} +\usage{ +aggregate_group_edid(cells, eif_matrix, cell_index, panel_obj, alpha) +} +\arguments{ +\item{cells}{list of \code{edid_cell_result} objects} + +\item{eif_matrix}{n x n_cells numeric matrix (or NULL)} + +\item{cell_index}{data.frame with columns \code{group}, \code{time}, +\code{cell_id}, \code{is_pre}} + +\item{panel_obj}{panel object} + +\item{alpha}{significance level} +} +\value{ +named list, one entry per cohort; each entry is a list with +\code{group}, \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +\code{t_stat}, \code{p_value}, \code{eif_agg} +} +\description{ +For each cohort \code{g}, computes the equal-time-weighted average ATT over +all post-treatment cells \code{(g, t)} with \code{t >= g}. +Group aggregation uses equal weights so there is no WIF correction. +} +\keyword{internal} diff --git a/man/aggregate_overall_edid.Rd b/man/aggregate_overall_edid.Rd new file mode 100644 index 0000000..1ea95fc --- /dev/null +++ b/man/aggregate_overall_edid.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggregate.R +\name{aggregate_overall_edid} +\alias{aggregate_overall_edid} +\title{Aggregate cell-level ATTs into an overall ATT} +\usage{ +aggregate_overall_edid(cells, eif_matrix, cell_index, panel_obj, alpha) +} +\arguments{ +\item{cells}{list of \code{edid_cell_result} objects (ordered by cell_id)} + +\item{eif_matrix}{n x n_cells numeric matrix (or NULL if EIF not stored)} + +\item{cell_index}{data.frame with columns \code{group}, \code{time}, +\code{cell_id}, \code{is_pre}} + +\item{panel_obj}{panel object} + +\item{alpha}{significance level} +} +\value{ +named list: \code{att}, \code{se}, \code{ci_lower}, \code{ci_upper}, +\code{t_stat}, \code{p_value}, \code{eif_agg} +} +\description{ +Uses cohort-share weights \eqn{q_k = \pi_{g_k}} over post-treatment cells, +normalized to sum to 1. Includes WIF correction for estimated weights. +} +\keyword{internal} diff --git a/man/as.data.frame.edid_fit.Rd b/man/as.data.frame.edid_fit.Rd new file mode 100644 index 0000000..127051a --- /dev/null +++ b/man/as.data.frame.edid_fit.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-methods.R +\name{as.data.frame.edid_fit} +\alias{as.data.frame.edid_fit} +\title{Coerce edid_fit to a data.frame} +\usage{ +\method{as.data.frame}{edid_fit}(x, which = c("att_gt", "overall", "event_study", "group"), ...) +} +\arguments{ +\item{x}{an \code{edid_fit} object} + +\item{which}{character: one of \code{"att_gt"}, \code{"overall"}, +\code{"event_study"}, \code{"group"}} + +\item{...}{additional arguments (ignored)} +} +\value{ +data.frame +} +\description{ +Coerce edid_fit to a data.frame +} diff --git a/man/build_cluster_index.Rd b/man/build_cluster_index.Rd new file mode 100644 index 0000000..5ee77bb --- /dev/null +++ b/man/build_cluster_index.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-data.R +\name{build_cluster_index} +\alias{build_cluster_index} +\title{Build cluster integer index from cluster id column} +\usage{ +build_cluster_index(dt, unit, cluster, all_units) +} +\arguments{ +\item{dt}{data.table (long format), sorted by unit then time} + +\item{unit}{character scalar: unit id column name} + +\item{cluster}{character scalar: cluster id column name} + +\item{all_units}{sorted vector of unique unit ids} +} +\value{ +integer vector length n (values 1..G) +} +\description{ +Build cluster integer index from cluster id column +} +\keyword{internal} diff --git a/man/check_condition_edid.Rd b/man/check_condition_edid.Rd new file mode 100644 index 0000000..a1a7ed1 --- /dev/null +++ b/man/check_condition_edid.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-linalg.R +\name{check_condition_edid} +\alias{check_condition_edid} +\title{Condition number of a matrix via SVD} +\usage{ +check_condition_edid(mat) +} +\arguments{ +\item{mat}{numeric matrix} +} +\value{ +scalar: max singular value / min positive singular value. +Returns \code{Inf} if min singular value is 0. +} +\description{ +Condition number of a matrix via SVD +} +\keyword{internal} diff --git a/man/cluster_aggregate_edid.Rd b/man/cluster_aggregate_edid.Rd new file mode 100644 index 0000000..90c7f2e --- /dev/null +++ b/man/cluster_aggregate_edid.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-inference.R +\name{cluster_aggregate_edid} +\alias{cluster_aggregate_edid} +\title{Aggregate EIF to cluster level (centered)} +\usage{ +cluster_aggregate_edid(eif, cluster_indices) +} +\arguments{ +\item{eif}{numeric vector length n} + +\item{cluster_indices}{integer vector length n (values 1..G)} +} +\value{ +numeric vector length G (cluster sums, centered) +} +\description{ +Returns the vector of cluster sums of \code{eif}, mean-subtracted. +The small-sample correction \eqn{G/(G-1)} is applied in the SE formula +(in \code{safe_inference_edid}), not here. +} +\keyword{internal} diff --git a/man/coef.edid_fit.Rd b/man/coef.edid_fit.Rd new file mode 100644 index 0000000..e234804 --- /dev/null +++ b/man/coef.edid_fit.Rd @@ -0,0 +1,22 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-methods.R +\name{coef.edid_fit} +\alias{coef.edid_fit} +\title{Extract ATT coefficients from an edid_fit object} +\usage{ +\method{coef}{edid_fit}(object, which = c("att_gt", "overall", "event_study", "group"), ...) +} +\arguments{ +\item{object}{an \code{edid_fit} object} + +\item{which}{character: one of \code{"att_gt"}, \code{"overall"}, +\code{"event_study"}, \code{"group"}} + +\item{...}{additional arguments (ignored)} +} +\value{ +named numeric vector of ATT estimates +} +\description{ +Extract ATT coefficients from an edid_fit object +} diff --git a/man/compute_bootstrap_stats_edid.Rd b/man/compute_bootstrap_stats_edid.Rd new file mode 100644 index 0000000..afea400 --- /dev/null +++ b/man/compute_bootstrap_stats_edid.Rd @@ -0,0 +1,23 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-bootstrap.R +\name{compute_bootstrap_stats_edid} +\alias{compute_bootstrap_stats_edid} +\title{Compute bootstrap SE, CI, and p-value from a vector of bootstrap draws} +\usage{ +compute_bootstrap_stats_edid(boot_draws, att_hat, alpha = 0.05) +} +\arguments{ +\item{boot_draws}{numeric vector of length \code{n_bootstrap}} + +\item{att_hat}{scalar point estimate} + +\item{alpha}{significance level in (0, 1)} +} +\value{ +named list: \code{se_boot}, \code{ci_lower}, \code{ci_upper}, +\code{p_value_boot} +} +\description{ +Compute bootstrap SE, CI, and p-value from a vector of bootstrap draws +} +\keyword{internal} diff --git a/man/compute_efficient_weights_edid.Rd b/man/compute_efficient_weights_edid.Rd new file mode 100644 index 0000000..856f775 --- /dev/null +++ b/man/compute_efficient_weights_edid.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-nocov.R +\name{compute_efficient_weights_edid} +\alias{compute_efficient_weights_edid} +\title{Compute efficient inverse-covariance weights} +\usage{ +compute_efficient_weights_edid(omega_star) +} +\arguments{ +\item{omega_star}{numeric matrix H x H} +} +\value{ +numeric vector length H, summing to 1 +} +\description{ +Implements \eqn{w = (\Omega^{*-1} \mathbf{1}) / (\mathbf{1}' \Omega^{*-1} \mathbf{1})} +with fallback to uniform weights when the matrix is degenerate. +} +\keyword{internal} diff --git a/man/compute_eif_nocov_edid.Rd b/man/compute_eif_nocov_edid.Rd new file mode 100644 index 0000000..95ae750 --- /dev/null +++ b/man/compute_eif_nocov_edid.Rd @@ -0,0 +1,38 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-nocov.R +\name{compute_eif_nocov_edid} +\alias{compute_eif_nocov_edid} +\title{Compute the no-covariate efficient influence function for a (g, t) cell} +\usage{ +compute_eif_nocov_edid( + target_g, + target_t, + pairs, + weights, + panel_obj, + att_gt, + pt_assumption +) +} +\arguments{ +\item{target_g}{scalar cohort value} + +\item{target_t}{scalar time period} + +\item{pairs}{data.frame with columns \code{gp} and \code{tpre}; H rows} + +\item{weights}{numeric vector length H (efficient weights)} + +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{att_gt}{scalar ATT estimate for this cell} + +\item{pt_assumption}{\code{"all"} or \code{"post"}} +} +\value{ +numeric vector length n (zero-mean by construction) +} +\description{ +Compute the no-covariate efficient influence function for a (g, t) cell +} +\keyword{internal} diff --git a/man/compute_eif_se_edid.Rd b/man/compute_eif_se_edid.Rd new file mode 100644 index 0000000..bb98559 --- /dev/null +++ b/man/compute_eif_se_edid.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-inference.R +\name{compute_eif_se_edid} +\alias{compute_eif_se_edid} +\title{Compute SE from EIF vector} +\usage{ +compute_eif_se_edid(eif_vec, n) +} +\arguments{ +\item{eif_vec}{numeric vector (may be cluster-aggregated sums)} + +\item{n}{integer denominator (number of units or clusters)} +} +\value{ +scalar SE +} +\description{ +\deqn{SE = \sqrt{\sum_i \text{eif}_i^2 / n^2}} +} +\keyword{internal} diff --git a/man/compute_generated_outcomes_nocov_edid.Rd b/man/compute_generated_outcomes_nocov_edid.Rd new file mode 100644 index 0000000..dc23439 --- /dev/null +++ b/man/compute_generated_outcomes_nocov_edid.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-nocov.R +\name{compute_generated_outcomes_nocov_edid} +\alias{compute_generated_outcomes_nocov_edid} +\title{Compute generated-outcome scalars for each valid pair} +\usage{ +compute_generated_outcomes_nocov_edid( + target_g, + target_t, + pairs, + panel_obj, + pt_assumption +) +} +\arguments{ +\item{target_g}{scalar cohort value} + +\item{target_t}{scalar time period} + +\item{pairs}{data.frame with columns \code{gp} and \code{tpre}; H rows} + +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{pt_assumption}{\code{"all"} or \code{"post"}} +} +\value{ +numeric vector length H +} +\description{ +Compute generated-outcome scalars for each valid pair +} +\keyword{internal} diff --git a/man/compute_omega_star_nocov_edid.Rd b/man/compute_omega_star_nocov_edid.Rd new file mode 100644 index 0000000..d87dfbc --- /dev/null +++ b/man/compute_omega_star_nocov_edid.Rd @@ -0,0 +1,33 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-nocov.R +\name{compute_omega_star_nocov_edid} +\alias{compute_omega_star_nocov_edid} +\title{Compute the Omega* covariance matrix for the no-covariate EDiD path} +\usage{ +compute_omega_star_nocov_edid( + target_g, + target_t, + pairs, + panel_obj, + pt_assumption +) +} +\arguments{ +\item{target_g}{scalar cohort value} + +\item{target_t}{scalar time period} + +\item{pairs}{data.frame with columns \code{gp} and \code{tpre}; H rows} + +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{pt_assumption}{\code{"all"} or \code{"post"}} +} +\value{ +numeric matrix H x H +} +\description{ +Builds the \eqn{H \times H} sample covariance matrix of the identifying +moments for cell \code{(target_g, target_t)}. +} +\keyword{internal} diff --git a/man/compute_pseudoinverse_edid.Rd b/man/compute_pseudoinverse_edid.Rd new file mode 100644 index 0000000..0f7d899 --- /dev/null +++ b/man/compute_pseudoinverse_edid.Rd @@ -0,0 +1,21 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-linalg.R +\name{compute_pseudoinverse_edid} +\alias{compute_pseudoinverse_edid} +\title{SVD-based Moore-Penrose pseudoinverse} +\usage{ +compute_pseudoinverse_edid(mat, tol = NULL) +} +\arguments{ +\item{mat}{numeric matrix} + +\item{tol}{tolerance for zero singular values; defaults to +\code{max(dim(mat)) * max(svd$d) * .Machine$double.eps}} +} +\value{ +matrix of same dimensions as \code{t(mat)} +} +\description{ +SVD-based Moore-Penrose pseudoinverse +} +\keyword{internal} diff --git a/man/compute_wif_contribution_edid.Rd b/man/compute_wif_contribution_edid.Rd new file mode 100644 index 0000000..d9203bb --- /dev/null +++ b/man/compute_wif_contribution_edid.Rd @@ -0,0 +1,41 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggregate.R +\name{compute_wif_contribution_edid} +\alias{compute_wif_contribution_edid} +\title{Compute WIF (weight influence function) correction for aggregated EIF} +\usage{ +compute_wif_contribution_edid( + weight_fn, + cells, + eif_matrix, + cell_index, + panel_obj, + agg_att +) +} +\arguments{ +\item{weight_fn}{function(cells, cell_index, panel_obj) that returns a named +numeric vector of normalized weights \eqn{q_k} for all post-treatment cells; +names are cell_ids (character)} + +\item{cells}{list of \code{edid_cell_result} objects} + +\item{eif_matrix}{n x n_cells numeric matrix (or NULL)} + +\item{cell_index}{data.frame with columns \code{group}, \code{time}, +\code{cell_id}, \code{is_pre}} + +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{agg_att}{scalar: the already-computed aggregated ATT (used for WIF)} +} +\value{ +numeric vector length n: WIF correction to add to aggregated EIF +} +\description{ +Corrects the aggregated EIF for estimation error in the cohort-share weights +\eqn{\pi_g = n_g / n}. The correction accounts for the fact that \eqn{\pi_g} +is estimated from data and therefore contributes to the variance of the +aggregated estimator. +} +\keyword{internal} diff --git a/man/cov_nn_edid.Rd b/man/cov_nn_edid.Rd new file mode 100644 index 0000000..0a558a2 --- /dev/null +++ b/man/cov_nn_edid.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-utils.R +\name{cov_nn_edid} +\alias{cov_nn_edid} +\title{Biased sample covariance (divide by n, not n-1)} +\usage{ +cov_nn_edid(x, y) +} +\arguments{ +\item{x}{numeric vector} + +\item{y}{numeric vector, same length as x} +} +\value{ +scalar +} +\description{ +Biased sample covariance (divide by n, not n-1) +} +\keyword{internal} diff --git a/man/edid.Rd b/man/edid.Rd new file mode 100644 index 0000000..7b9a3ff --- /dev/null +++ b/man/edid.Rd @@ -0,0 +1,158 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid.R +\name{edid} +\alias{edid} +\title{Efficient Difference-in-Differences Estimator} +\usage{ +edid( + data, + outcome, + unit, + time, + first_treat, + covariates = NULL, + pt_assumption = c("all", "post"), + alpha = 0.05, + cluster = NULL, + control_group = c("never_treated", "last_cohort"), + n_bootstrap = 0L, + bootstrap_weights = c("rademacher", "mammen", "webb"), + seed = NULL, + anticipation = 0L, + aggregate = c("all", "overall", "event_study", "group", "none"), + balance_e = NULL, + survey_design = NULL, + store_eif = FALSE +) +} +\arguments{ +\item{data}{A \code{data.frame}, \code{data.table}, or tibble in long format +(one row per unit-time observation).} + +\item{outcome}{Character scalar: name of the outcome column (must be numeric +with no missing or non-finite values).} + +\item{unit}{Character scalar: name of the unit identifier column.} + +\item{time}{Character scalar: name of the time period column (numeric).} + +\item{first_treat}{Character scalar: name of the column recording each unit's +first treatment period. Never-treated units should have \code{Inf} (or +\code{NA} is not accepted --- use \code{Inf} explicitly).} + +\item{covariates}{Character vector of covariate column names, or \code{NULL} +(default). \strong{Currently not implemented}: passing non-NULL triggers an +error.} + +\item{pt_assumption}{Parallel-trends assumption regime. One of: +\describe{ +\item{\code{"all"}}{PT-All: parallel trends holds for all pre-treatment +periods (default). Uses all valid \eqn{(g', t_{pre})} pairs.} +\item{\code{"post"}}{PT-Post: parallel trends holds only for the period +immediately before treatment. Each cell uses a single DiD moment.} +}} + +\item{alpha}{Significance level for confidence intervals. Default \code{0.05}.} + +\item{cluster}{Character scalar naming a time-invariant cluster variable in +\code{data}, or \code{NULL} for no clustering (default). When supplied, +cluster-robust standard errors are computed via the sandwich EIF formula.} + +\item{control_group}{Control group definition. One of: +\describe{ +\item{\code{"never_treated"}}{Use never-treated units (default).} +\item{\code{"last_cohort"}}{Use the last-treated cohort as +pseudo-controls (relabeled as never-treated internally).} +}} + +\item{n_bootstrap}{Non-negative integer: number of multiplier bootstrap draws. +\code{0} (default) returns analytical standard errors only.} + +\item{bootstrap_weights}{Distribution for multiplier weights. One of +\code{"rademacher"} (default), \code{"mammen"}, or \code{"webb"}.} + +\item{seed}{Integer seed for reproducibility of bootstrap draws, or +\code{NULL} (default, no seed set).} + +\item{anticipation}{Non-negative integer: number of anticipation periods. +Default \code{0L}. The effective treatment start for cohort \eqn{g} is +\eqn{g - \text{anticipation}}.} + +\item{aggregate}{Which aggregations to compute. One or more of +\code{"all"} (default), \code{"overall"}, \code{"event_study"}, +\code{"group"}, or \code{"none"}.} + +\item{balance_e}{Integer or \code{NULL}: if not \code{NULL}, restricts the +event-study aggregation to relative times in +\eqn{[-\text{balance\_e}, \text{balance\_e}]}.} + +\item{survey_design}{Always \code{NULL}. Survey designs are not yet +implemented; passing a non-NULL value triggers an error.} + +\item{store_eif}{Logical: if \code{TRUE}, store the full \eqn{n \times K} +EIF matrix in \code{edid_fit$eif}. Default \code{FALSE}. The EIF is +always computed internally when \code{n_bootstrap > 0}.} +} +\value{ +An object of class \code{edid_fit} (a list) with elements: +\describe{ +\item{\code{call}}{The matched call.} +\item{\code{att_gt}}{data.frame of cell-level estimates (group, time, +att, se, ci_lower, ci_upper, t_stat, p_value, is_pre).} +\item{\code{overall}}{List: overall ATT with SE and CI.} +\item{\code{event_study}}{List of per-relative-time ATTs.} +\item{\code{group}}{List of per-cohort ATTs.} +\item{\code{eif}}{EIF matrix or \code{NULL}.} +\item{\code{bootstrap}}{Bootstrap results or \code{NULL}.} +} +} +\description{ +Estimates group-time average treatment effects \eqn{ATT(g, t)} for staggered +adoption designs using the Efficient DiD (EDiD) estimator of Chen, Sant'Anna +& Xie (2025). The estimator combines all valid DiD identifying moments for +each \eqn{(g, t)} cell with optimal inverse-covariance weights to achieve +minimum asymptotic variance. +} +\examples{ +# Simulate a simple balanced panel with staggered adoption +set.seed(42) +n_units <- 100 +n_periods <- 6 +unit_ids <- rep(1:n_units, each = n_periods) +time_ids <- rep(1:n_periods, times = n_units) +# Assign cohorts: 1/3 treated in period 3, 1/3 in period 5, 1/3 never +cohort_assign <- rep( + c(3, 5, Inf), + times = c(ceiling(n_units / 3), + ceiling(n_units / 3), + n_units - 2 * ceiling(n_units / 3)) +)[1:n_units] +first_treat_vec <- cohort_assign[unit_ids] +# Generate outcomes: ATT = 1 for treated post-treatment +treat_effect <- as.numeric(time_ids >= first_treat_vec) +y_vals <- 0.5 * time_ids + treat_effect + rnorm(n_units * n_periods, sd = 0.5) +panel_df <- data.frame( + id = unit_ids, + period = time_ids, + y = y_vals, + first_treat = first_treat_vec +) +# Fit EDiD (no-covariate, PT-All, analytical SE) +fit <- edid( + data = panel_df, + outcome = "y", + unit = "id", + time = "period", + first_treat = "first_treat", + pt_assumption = "all" +) +# View overall ATT +fit$overall$att +# Extract cell-level estimates +head(fit$att_gt) + +} +\references{ +Chen, L., Sant'Anna, P. H. C., & Xie, Y. (2025). +\emph{Efficient Difference-in-Differences}. Working paper. +} diff --git a/man/enumerate_valid_pairs_edid.Rd b/man/enumerate_valid_pairs_edid.Rd new file mode 100644 index 0000000..aeb6703 --- /dev/null +++ b/man/enumerate_valid_pairs_edid.Rd @@ -0,0 +1,50 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-pairs.R +\name{enumerate_valid_pairs_edid} +\alias{enumerate_valid_pairs_edid} +\title{Enumerate valid comparison pairs for a target (g, t) cell} +\usage{ +enumerate_valid_pairs_edid( + target_g, + treatment_groups, + time_periods, + period_1, + pt_assumption, + anticipation = 0L, + never_treated_val = Inf +) +} +\arguments{ +\item{target_g}{scalar: treatment cohort being estimated} + +\item{treatment_groups}{sorted numeric vector of all finite cohort values} + +\item{time_periods}{sorted numeric vector of all time periods in the panel} + +\item{period_1}{scalar: universal first period} + +\item{pt_assumption}{character: \code{"all"} or \code{"post"}} + +\item{anticipation}{integer >= 0} + +\item{never_treated_val}{value used to represent the never-treated cohort +(default \code{Inf})} +} +\value{ +data.frame with columns \code{gp} (comparison cohort) and +\code{tpre} (pre-period). May have 0 rows. +} +\description{ +Constructs the set \eqn{H_{gt}} of valid \code{(g', t_pre)} pairs used to +form identifying DiD moments for cohort \code{target_g} at time \code{target_t}. +} +\details{ +Under \strong{PT-Post}: returns exactly one pair \code{(Inf, target_g - 1 - anticipation)}, +or a 0-row data.frame if that pre-period does not exist in \code{time_periods} or +equals \code{period_1}. + +Under \strong{PT-All}: returns all \code{(gp, tpre)} pairs where \code{gp} ranges +over all cohorts (including never-treated) and \code{tpre} is a valid pre-period +strictly less than the effective treatment start of \code{gp}, excluding \code{period_1}. +} +\keyword{internal} diff --git a/man/fit_edid_cells.Rd b/man/fit_edid_cells.Rd new file mode 100644 index 0000000..bc4bffe --- /dev/null +++ b/man/fit_edid_cells.Rd @@ -0,0 +1,43 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-fit.R +\name{fit_edid_cells} +\alias{fit_edid_cells} +\title{Fit all (g, t) cells for the EDiD estimator} +\usage{ +fit_edid_cells( + panel_obj, + pt_assumption, + alpha, + store_eif, + covariates, + need_eif = FALSE +) +} +\arguments{ +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{pt_assumption}{character: \code{"all"} or \code{"post"}} + +\item{alpha}{significance level in (0, 1)} + +\item{store_eif}{logical: if TRUE, include EIF vectors in returned cells} + +\item{covariates}{NULL (covariate path is a stub)} + +\item{need_eif}{logical: if TRUE, always store EIF regardless of store_eif +(used internally when \code{n_bootstrap > 0})} +} +\value{ +list with elements: +\describe{ +\item{\code{cells}}{list of \code{edid_cell_result} objects} +\item{\code{eif_matrix}}{n x n_valid_cells numeric matrix, or NULL} +\item{\code{cell_index}}{data.frame: group, time, cell_id, is_pre} +} +} +\description{ +Iterates over all treatment cohorts and all time periods (excluding +\code{period_1}), computes point estimates, EIFs, and analytical SEs for +each cell. +} +\keyword{internal} diff --git a/man/generate_multiplier_weights_edid.Rd b/man/generate_multiplier_weights_edid.Rd new file mode 100644 index 0000000..c3a6775 --- /dev/null +++ b/man/generate_multiplier_weights_edid.Rd @@ -0,0 +1,36 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-bootstrap.R +\name{generate_multiplier_weights_edid} +\alias{generate_multiplier_weights_edid} +\title{Generate multiplier bootstrap weights} +\usage{ +generate_multiplier_weights_edid( + n, + n_bootstrap, + type = "rademacher", + cluster_indices = NULL, + seed = NULL +) +} +\arguments{ +\item{n}{integer: number of units} + +\item{n_bootstrap}{positive integer: number of bootstrap draws} + +\item{type}{character: \code{"rademacher"} (default), \code{"mammen"}, +or \code{"webb"}} + +\item{cluster_indices}{integer vector length n (values 1..G) or NULL} + +\item{seed}{integer seed or NULL} +} +\value{ +numeric matrix n x n_bootstrap +} +\description{ +Returns an \code{n x n_bootstrap} matrix of multiplier weights drawn from +the specified distribution. When \code{cluster_indices} is supplied, +weights are drawn at the cluster level (G x n_bootstrap) and then +expanded to unit level by repeating within cluster. +} +\keyword{internal} diff --git a/man/prepare_edid_panel.Rd b/man/prepare_edid_panel.Rd new file mode 100644 index 0000000..10022b3 --- /dev/null +++ b/man/prepare_edid_panel.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-data.R +\name{prepare_edid_panel} +\alias{prepare_edid_panel} +\title{Prepare the panel object used throughout edid estimation} +\usage{ +prepare_edid_panel( + data, + outcome, + unit, + time, + first_treat, + covariates = NULL, + cluster = NULL, + control_group = "never_treated", + anticipation = 0L +) +} +\arguments{ +\item{data}{data.frame (or data.table / tibble) already validated} + +\item{outcome}{character scalar: outcome column name} + +\item{unit}{character scalar: unit id column name} + +\item{time}{character scalar: time column name} + +\item{first_treat}{character scalar: first-treatment-period column name} + +\item{covariates}{NULL (stub)} + +\item{cluster}{character scalar or NULL} + +\item{control_group}{\code{"never_treated"} or \code{"last_cohort"}} + +\item{anticipation}{non-negative integer} +} +\value{ +a \code{panel_obj} list; see spec Section 5.1 +} +\description{ +Reshapes the long-format input \code{data} into a wide outcome matrix and +builds all masks and maps needed by downstream functions. +} +\keyword{internal} diff --git a/man/print.edid_fit.Rd b/man/print.edid_fit.Rd new file mode 100644 index 0000000..329ba21 --- /dev/null +++ b/man/print.edid_fit.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-methods.R +\name{print.edid_fit} +\alias{print.edid_fit} +\title{Print method for edid_fit objects} +\usage{ +\method{print}{edid_fit}(x, ...) +} +\arguments{ +\item{x}{an \code{edid_fit} object} + +\item{...}{additional arguments (currently ignored)} +} +\value{ +\code{x} invisibly +} +\description{ +Calls \code{summary.edid_fit()} and returns the object invisibly. +} diff --git a/man/run_multiplier_bootstrap_edid.Rd b/man/run_multiplier_bootstrap_edid.Rd new file mode 100644 index 0000000..ac741b2 --- /dev/null +++ b/man/run_multiplier_bootstrap_edid.Rd @@ -0,0 +1,52 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-bootstrap.R +\name{run_multiplier_bootstrap_edid} +\alias{run_multiplier_bootstrap_edid} +\title{Run the multiplier bootstrap for EDiD estimates} +\usage{ +run_multiplier_bootstrap_edid( + cells, + eif_matrix, + cell_index, + panel_obj, + n_bootstrap, + bootstrap_weights = "rademacher", + seed = NULL, + aggregate = "all", + balance_e = NULL, + alpha = 0.05 +) +} +\arguments{ +\item{cells}{list of \code{edid_cell_result} objects} + +\item{eif_matrix}{n x n_cells numeric matrix of stored EIFs} + +\item{cell_index}{data.frame with columns \code{group}, \code{time}, +\code{cell_id}, \code{is_pre}} + +\item{panel_obj}{panel object from \code{prepare_edid_panel()}} + +\item{n_bootstrap}{positive integer number of bootstrap draws} + +\item{bootstrap_weights}{character: \code{"rademacher"}, \code{"mammen"}, +or \code{"webb"}} + +\item{seed}{integer seed or NULL} + +\item{aggregate}{character: which aggregations to return} + +\item{balance_e}{integer or NULL} + +\item{alpha}{significance level} +} +\value{ +list with elements \code{overall_draws}, \code{event_study_draws}, +\code{group_draws}, \code{n_bootstrap}, \code{weight_type}, \code{seed} +} +\description{ +Generates \code{n_bootstrap} perturbed versions of all cell-level ATTs +by multiplying stored EIF vectors with multiplier weights, then re-aggregates +using the same fixed cohort-share weights. +} +\keyword{internal} diff --git a/man/safe_inference_edid.Rd b/man/safe_inference_edid.Rd new file mode 100644 index 0000000..579e339 --- /dev/null +++ b/man/safe_inference_edid.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-inference.R +\name{safe_inference_edid} +\alias{safe_inference_edid} +\title{Safely compute SE, CI, and p-value from an EIF vector} +\usage{ +safe_inference_edid(eif, cluster_indices = NULL, alpha = 0.05, att = NA_real_) +} +\arguments{ +\item{eif}{numeric vector length n (or NULL, for NA cells)} + +\item{cluster_indices}{integer vector length n (1..G) or NULL} + +\item{alpha}{significance level in (0, 1)} + +\item{att}{scalar ATT estimate (used for t-stat; may be NA for inference check)} +} +\value{ +named list: +\code{se}, \code{ci_lower}, \code{ci_upper}, \code{t_stat}, +\code{p_value}, \code{inference_valid} +} +\description{ +Dispatches to \code{compute_eif_se_edid()} with optional cluster aggregation. +If the resulting SE is not valid (zero, NA, or non-finite), all inference +results are set to \code{NA}. +} +\keyword{internal} diff --git a/man/safe_mean_edid.Rd b/man/safe_mean_edid.Rd new file mode 100644 index 0000000..a71202a --- /dev/null +++ b/man/safe_mean_edid.Rd @@ -0,0 +1,18 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-utils.R +\name{safe_mean_edid} +\alias{safe_mean_edid} +\title{Safe mean: returns NA on empty vector instead of NaN} +\usage{ +safe_mean_edid(x) +} +\arguments{ +\item{x}{numeric vector} +} +\value{ +scalar +} +\description{ +Safe mean: returns NA on empty vector instead of NaN +} +\keyword{internal} diff --git a/man/solve_ols_edid.Rd b/man/solve_ols_edid.Rd new file mode 100644 index 0000000..030b5f1 --- /dev/null +++ b/man/solve_ols_edid.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-linalg.R +\name{solve_ols_edid} +\alias{solve_ols_edid} +\title{Weighted OLS helper} +\usage{ +solve_ols_edid(X, y, weights = NULL) +} +\arguments{ +\item{X}{numeric matrix (n x p)} + +\item{y}{numeric vector length n} + +\item{weights}{numeric vector length n (NULL = uniform)} +} +\value{ +named list with elements \code{coef}, \code{fitted}, \code{residuals} +} +\description{ +Computes \eqn{\hat\beta = (X'WX)^{-1} X'Wy} using \code{.lm.fit()}. +Falls back to SVD-based pseudoinverse if the normal equations are +numerically singular. +} +\keyword{internal} diff --git a/man/summary.edid_fit.Rd b/man/summary.edid_fit.Rd new file mode 100644 index 0000000..eca2595 --- /dev/null +++ b/man/summary.edid_fit.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-methods.R +\name{summary.edid_fit} +\alias{summary.edid_fit} +\title{Summary method for edid_fit objects} +\usage{ +\method{summary}{edid_fit}(object, ...) +} +\arguments{ +\item{object}{an \code{edid_fit} object} + +\item{...}{additional arguments (currently ignored)} +} +\value{ +\code{object} invisibly +} +\description{ +Prints a structured summary of the EDiD estimation results including +metadata, the cell-level ATT table, and aggregated estimates. +} diff --git a/man/validate_edid_inputs.Rd b/man/validate_edid_inputs.Rd new file mode 100644 index 0000000..cd007d1 --- /dev/null +++ b/man/validate_edid_inputs.Rd @@ -0,0 +1,58 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-validate.R +\name{validate_edid_inputs} +\alias{validate_edid_inputs} +\title{Validate inputs to \code{edid()}} +\usage{ +validate_edid_inputs( + data, + outcome, + unit, + time, + first_treat, + covariates, + pt_assumption, + alpha, + cluster, + control_group, + n_bootstrap, + anticipation, + survey_design +) +} +\arguments{ +\item{data}{data.frame or coercible} + +\item{outcome}{character scalar: outcome column name} + +\item{unit}{character scalar: unit id column name} + +\item{time}{character scalar: time column name} + +\item{first_treat}{character scalar: first-treatment-period column name} + +\item{covariates}{character vector or NULL} + +\item{pt_assumption}{character scalar, already matched via \code{match.arg}} + +\item{alpha}{numeric scalar in (0, 1)} + +\item{cluster}{character scalar or NULL} + +\item{control_group}{character scalar, already matched via \code{match.arg}} + +\item{n_bootstrap}{non-negative integer} + +\item{anticipation}{non-negative integer} + +\item{survey_design}{always NULL (survey not yet implemented)} +} +\value{ +invisibly TRUE +} +\description{ +Performs all structural and type checks on user-supplied arguments. +Returns invisibly \code{TRUE} on success; stops with an informative message +on any failure. +} +\keyword{internal} diff --git a/man/vcov.edid_fit.Rd b/man/vcov.edid_fit.Rd new file mode 100644 index 0000000..85e6940 --- /dev/null +++ b/man/vcov.edid_fit.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-methods.R +\name{vcov.edid_fit} +\alias{vcov.edid_fit} +\title{Extract variance-covariance matrix from an edid_fit object} +\usage{ +\method{vcov}{edid_fit}(object, which = c("att_gt", "overall", "event_study", "group"), ...) +} +\arguments{ +\item{object}{an \code{edid_fit} object} + +\item{which}{character: one of \code{"att_gt"}, \code{"overall"}, +\code{"event_study"}, \code{"group"}} + +\item{...}{additional arguments (ignored)} +} +\value{ +square numeric matrix +} +\description{ +Returns the outer product of aggregated EIF vectors, scaled by \eqn{1/n^2}. +When bootstrap inference is used, returns a diagonal matrix of bootstrap +variance estimates. +} From aaec7fc9f898915538abd5917a3a78feec46d3b0 Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Sat, 11 Apr 2026 15:54:06 -0400 Subject: [PATCH 02/12] builder: fix 4 edid bugs (EIF centering, inference validity, bootstrap field names) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - BUG-1: remove spurious `eif - att_gt` subtraction in compute_eif_nocov_edid(); the score is already zero-mean by construction (each group contribution is demeaned) - BUG-2: safe_inference_edid() now returns inference_valid=FALSE (with non-NA se but NA CIs/p-value) when att is non-finite, fixing the valid=TRUE/NA-CI inconsistency - BUG-3: resolves automatically from BUG-1 fix - BUG-4: rename overall_draws→overall_b, event_study_draws→event_study_b, group_draws→group_b in run_multiplier_bootstrap_edid() and update callers in edid.R Co-Authored-By: Claude Sonnet 4.6 --- R/edid-bootstrap.R | 38 +++++++++++++++++++------------------- R/edid-inference.R | 26 ++++++++++++++++++++------ R/edid-nocov.R | 5 +++-- R/edid.R | 12 ++++++------ 4 files changed, 48 insertions(+), 33 deletions(-) diff --git a/R/edid-bootstrap.R b/R/edid-bootstrap.R index 14ae0bd..7e27011 100644 --- a/R/edid-bootstrap.R +++ b/R/edid-bootstrap.R @@ -20,8 +20,8 @@ #' @param balance_e integer or NULL #' @param alpha significance level #' -#' @return list with elements \code{overall_draws}, \code{event_study_draws}, -#' \code{group_draws}, \code{n_bootstrap}, \code{weight_type}, \code{seed} +#' @return list with elements \code{overall_b}, \code{event_study_b}, +#' \code{group_b}, \code{n_bootstrap}, \code{weight_type}, \code{seed} #' @keywords internal run_multiplier_bootstrap_edid <- function( cells, eif_matrix, cell_index, panel_obj, @@ -67,15 +67,15 @@ run_multiplier_bootstrap_edid <- function( # ----------------------------------------------------------------------- # Overall bootstrap draws # ----------------------------------------------------------------------- - overall_draws <- NULL + overall_b <- NULL if (aggregate %in% c("all", "overall")) { - overall_draws <- drop(att_boot_mat %*% q_norm) # n_bootstrap vector + overall_b <- drop(att_boot_mat %*% q_norm) # n_bootstrap vector } # ----------------------------------------------------------------------- # Event-study bootstrap draws # ----------------------------------------------------------------------- - event_study_draws <- NULL + event_study_b <- NULL if (aggregate %in% c("all", "event_study")) { cell_index_v <- cell_index[cell_index$cell_id %in% post_ids_v, , drop = FALSE] cell_index_v$e <- cell_index_v$time - cell_index_v$group @@ -83,8 +83,8 @@ run_multiplier_bootstrap_edid <- function( cell_index_v <- cell_index_v[abs(cell_index_v$e) <= balance_e, , drop = FALSE] } unique_e <- sort(unique(cell_index_v$e)) - event_study_draws <- vector("list", length(unique_e)) - names(event_study_draws) <- as.character(unique_e) + event_study_b <- vector("list", length(unique_e)) + names(event_study_b) <- as.character(unique_e) for (ii in seq_along(unique_e)) { e_val <- unique_e[ii] @@ -99,18 +99,18 @@ run_multiplier_bootstrap_edid <- function( e_Su <- sum(e_pi) if (e_Su < EDID_DENOM_EPS) next e_q <- e_pi / e_Su - event_study_draws[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% e_q) + event_study_b[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% e_q) } } # ----------------------------------------------------------------------- # Group bootstrap draws # ----------------------------------------------------------------------- - group_draws <- NULL + group_b <- NULL if (aggregate %in% c("all", "group")) { - tgroups <- panel_obj$treatment_groups - group_draws <- vector("list", length(tgroups)) - names(group_draws) <- as.character(tgroups) + tgroups <- panel_obj$treatment_groups + group_b <- vector("list", length(tgroups)) + names(group_b) <- as.character(tgroups) for (ii in seq_along(tgroups)) { g_val <- tgroups[ii] @@ -121,17 +121,17 @@ run_multiplier_bootstrap_edid <- function( if (length(col_idx) == 0L) next m_g <- length(col_idx) g_q <- rep(1 / m_g, m_g) - group_draws[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% g_q) + group_b[[ii]] <- drop(att_boot_mat[, col_idx, drop = FALSE] %*% g_q) } } list( - overall_draws = overall_draws, - event_study_draws = event_study_draws, - group_draws = group_draws, - n_bootstrap = n_bootstrap, - weight_type = bootstrap_weights, - seed = seed + overall_b = overall_b, + event_study_b = event_study_b, + group_b = group_b, + n_bootstrap = n_bootstrap, + weight_type = bootstrap_weights, + seed = seed ) } diff --git a/R/edid-inference.R b/R/edid-inference.R index abe1823..653123b 100644 --- a/R/edid-inference.R +++ b/R/edid-inference.R @@ -40,18 +40,32 @@ safe_inference_edid <- function(eif, cluster_indices = NULL, alpha = 0.05, se <- sqrt((G / (G - 1)) * sum(cluster_sums^2) / (length(eif)^2)) } - valid <- is.finite(se) && se > EDID_SE_EPS + valid_se <- is.finite(se) && se > EDID_SE_EPS - if (!valid) return(na_result) + if (!valid_se) return(na_result) + + # att must be finite for CIs and p-value to be meaningful. + # If att is NA/non-finite, return the SE but mark inference as invalid + # (inference_valid = FALSE signals that CIs and p-value are not available). + if (!is.finite(att)) { + return(list( + se = se, + ci_lower = NA_real_, + ci_upper = NA_real_, + t_stat = NA_real_, + p_value = NA_real_, + inference_valid = FALSE + )) + } z_crit <- qnorm(1 - alpha / 2) - t_stat <- if (is.finite(att)) att / se else NA_real_ - p_value <- if (is.finite(t_stat)) 2 * pnorm(-abs(t_stat)) else NA_real_ + t_stat <- att / se + p_value <- 2 * pnorm(-abs(t_stat)) list( se = se, - ci_lower = if (is.finite(att)) att - z_crit * se else NA_real_, - ci_upper = if (is.finite(att)) att + z_crit * se else NA_real_, + ci_lower = att - z_crit * se, + ci_upper = att + z_crit * se, t_stat = t_stat, p_value = p_value, inference_valid = TRUE diff --git a/R/edid-nocov.R b/R/edid-nocov.R index a3d9d6b..1033c9d 100644 --- a/R/edid-nocov.R +++ b/R/edid-nocov.R @@ -349,7 +349,8 @@ compute_eif_nocov_edid <- function( } } - # Center: EIF = score - ATT_hat - eif <- eif - att_gt + # The score accumulated above already has mean 0 by construction: + # each group's contribution is demeaned (delta_i - mean(delta)). + # The EIF is the score itself; do NOT subtract att_gt again. eif } diff --git a/R/edid.R b/R/edid.R index a558938..5ab9959 100644 --- a/R/edid.R +++ b/R/edid.R @@ -267,8 +267,8 @@ edid <- function( class(bootstrap_res) <- c("edid_bootstrap", "list") # Overwrite SEs/CIs with bootstrap versions - if (do_overall && !is.null(overall_res) && !is.null(bootstrap_res$overall_draws)) { - bs_ov <- compute_bootstrap_stats_edid(bootstrap_res$overall_draws, overall_res$att, alpha) + if (do_overall && !is.null(overall_res) && !is.null(bootstrap_res$overall_b)) { + bs_ov <- compute_bootstrap_stats_edid(bootstrap_res$overall_b, overall_res$att, alpha) overall_res$se <- bs_ov$se_boot overall_res$ci_lower <- bs_ov$ci_lower overall_res$ci_upper <- bs_ov$ci_upper @@ -279,9 +279,9 @@ edid <- function( } if (do_event_study && !is.null(event_study_res) && - !is.null(bootstrap_res$event_study_draws)) { + !is.null(bootstrap_res$event_study_b)) { for (e_nm in names(event_study_res)) { - draws <- bootstrap_res$event_study_draws[[e_nm]] + draws <- bootstrap_res$event_study_b[[e_nm]] if (is.null(draws)) next bs_es <- compute_bootstrap_stats_edid(draws, event_study_res[[e_nm]]$att, alpha) event_study_res[[e_nm]]$se <- bs_es$se_boot @@ -291,9 +291,9 @@ edid <- function( } } - if (do_group && !is.null(group_res) && !is.null(bootstrap_res$group_draws)) { + if (do_group && !is.null(group_res) && !is.null(bootstrap_res$group_b)) { for (g_nm in names(group_res)) { - draws <- bootstrap_res$group_draws[[g_nm]] + draws <- bootstrap_res$group_b[[g_nm]] if (is.null(draws)) next bs_gr <- compute_bootstrap_stats_edid(draws, group_res[[g_nm]]$att, alpha) group_res[[g_nm]]$se <- bs_gr$se_boot From 9266703c1569a7e4b4bf004556aa9c2cbf6d524f Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Sat, 11 Apr 2026 15:59:55 -0400 Subject: [PATCH 03/12] scriber: add edid() NEWS entry and architecture record Appended edid() feature bullet to NEWS.md under the 2.3.1.904 development header. Produced ARCHITECTURE.md and log-entry.md in the run directory documenting the EDiD module structure, panel_obj/edid_fit schemas, (g,t) cell loop, PT-All vs PT-Post pair enumeration, Omega* construction, aggregation/bootstrap flows, and 4 bug resolutions (BUG-1 through BUG-4). Co-Authored-By: Claude Sonnet 4.6 --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index aa6537c..88f191a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # did 2.3.1.904 + * Added `edid()`: efficient DiD estimator (Chen, Sant'Anna & Xie 2025) supporting PT-All and PT-Post parallel trends assumptions, analytical EIF-based standard errors (iid and cluster-robust), multiplier bootstrap inference (Rademacher, Mammen, Webb), and overall/event-study/group aggregation with WIF correction. + * Fixed bug where `faster_mode = TRUE` and `faster_mode = FALSE` produced different ATT estimates when sampling weights (`weightsname`) vary across time. The fast path was always using first-period weights; it now correctly uses the same period's weights as the slow path * New `fix_weights` argument in `att_gt()` gives users explicit control over how time-varying sampling weights are resolved in each 2x2 DiD comparison. Options: `NULL` (default, preserves existing behavior), `"varying"` (per-observation weights using RC estimators), `"base_period"` (fix at g-1 for all cells), `"first_period"` (fix at first period). See `?att_gt` for details From 2a6c4ae9fec8ca9884278d283eca080bf728672c Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Sat, 11 Apr 2026 16:09:56 -0400 Subject: [PATCH 04/12] Add edid(): efficient DiD estimator (Chen, Sant'Anna & Xie 2025) Implements the efficient DiD estimator from Chen, Sant'Anna & Xie (2025) supporting PT-All and PT-Post parallel trends assumptions. Features (Priorities 1-6): - Data validation and balanced-panel preprocessing - Valid-pair enumeration for PT-All and PT-Post regimes - Closed-form efficient DiD via inverse-covariance weights (no-cov path) - Analytical EIF-based SEs (iid and cluster-robust) - Overall, event-study, and group aggregation with WIF correction - Multiplier bootstrap (Rademacher, Mammen, Webb) with cluster expansion Deferred to follow-up: DR covariate path, survey support, Hausman pretest. 207 new edid tests pass; 777 full-suite pass; 0 regressions. Co-Authored-By: Claude Sonnet 4.6 --- man/run_multiplier_bootstrap_edid.Rd | 4 +- tests/testthat/helper-edid.R | 137 +++++++++++++ tests/testthat/test-edid-aggregate.R | 95 +++++++++ tests/testthat/test-edid-bootstrap.R | 137 +++++++++++++ tests/testthat/test-edid-inference.R | 96 +++++++++ tests/testthat/test-edid-integration.R | 255 ++++++++++++++++++++++++ tests/testthat/test-edid-nocov.R | 178 +++++++++++++++++ tests/testthat/test-edid-pairs.R | 164 +++++++++++++++ tests/testthat/test-edid-validate.R | 265 +++++++++++++++++++++++++ 9 files changed, 1329 insertions(+), 2 deletions(-) create mode 100644 tests/testthat/helper-edid.R create mode 100644 tests/testthat/test-edid-aggregate.R create mode 100644 tests/testthat/test-edid-bootstrap.R create mode 100644 tests/testthat/test-edid-inference.R create mode 100644 tests/testthat/test-edid-integration.R create mode 100644 tests/testthat/test-edid-nocov.R create mode 100644 tests/testthat/test-edid-pairs.R create mode 100644 tests/testthat/test-edid-validate.R diff --git a/man/run_multiplier_bootstrap_edid.Rd b/man/run_multiplier_bootstrap_edid.Rd index ac741b2..7544d22 100644 --- a/man/run_multiplier_bootstrap_edid.Rd +++ b/man/run_multiplier_bootstrap_edid.Rd @@ -41,8 +41,8 @@ or \code{"webb"}} \item{alpha}{significance level} } \value{ -list with elements \code{overall_draws}, \code{event_study_draws}, -\code{group_draws}, \code{n_bootstrap}, \code{weight_type}, \code{seed} +list with elements \code{overall_b}, \code{event_study_b}, +\code{group_b}, \code{n_bootstrap}, \code{weight_type}, \code{seed} } \description{ Generates \code{n_bootstrap} perturbed versions of all cell-level ATTs diff --git a/tests/testthat/helper-edid.R b/tests/testthat/helper-edid.R new file mode 100644 index 0000000..a18796b --- /dev/null +++ b/tests/testthat/helper-edid.R @@ -0,0 +1,137 @@ +# helper-edid.R +# Shared test data factories for edid() tests. +# Auto-loaded by testthat before any test file runs. + +#' Construct a minimal one-cohort balanced panel for testing +#' +#' @param n_treat Number of treated units (cohort g=3) +#' @param n_never Number of never-treated units +#' @param n_periods Number of time periods (periods 1..n_periods) +#' @param seed RNG seed for outcome generation +#' @return data.frame with columns: unit, time, outcome, first_treat +make_panel_1cohort <- function(n_treat = 20L, n_never = 20L, + n_periods = 5L, seed = 42L) { + set.seed(seed) + n <- n_treat + n_never + units <- seq_len(n) + times <- seq_len(n_periods) + + unit_ids <- rep(units, each = n_periods) + time_ids <- rep(times, times = n) + first_treat_vals <- c(rep(3L, n_treat * n_periods), # cohort g=3 + rep(Inf, n_never * n_periods)) # never treated + + # unit fixed effects + time trend + noise + unit_fe <- rep(rnorm(n, 0, 1), each = n_periods) + time_fe <- rep(seq(0, 0.5, length.out = n_periods), times = n) + noise <- rnorm(n * n_periods, 0, 0.5) + # Treatment effect of 2 for treated units in post periods + treated_post <- (unit_ids <= n_treat) & (time_ids >= 3L) + outcome <- unit_fe + time_fe + noise + 2 * treated_post + + data.frame( + unit = unit_ids, + time = time_ids, + outcome = outcome, + first_treat = first_treat_vals, + stringsAsFactors = FALSE + ) +} + +#' Construct a two-cohort staggered balanced panel for testing +#' +#' @param n_g3 Units in cohort g=3 +#' @param n_g5 Units in cohort g=5 +#' @param n_never Never-treated units +#' @param n_periods Time periods (1..n_periods) +#' @param seed RNG seed +#' @return data.frame with columns: unit, time, outcome, first_treat +make_panel_2cohort <- function(n_g3 = 15L, n_g5 = 15L, n_never = 20L, + n_periods = 7L, seed = 123L) { + set.seed(seed) + n <- n_g3 + n_g5 + n_never + units <- seq_len(n) + times <- seq_len(n_periods) + + unit_ids <- rep(units, each = n_periods) + time_ids <- rep(times, times = n) + first_treat_vals <- c( + rep(3L, n_g3 * n_periods), + rep(5L, n_g5 * n_periods), + rep(Inf, n_never * n_periods) + ) + + unit_fe <- rep(rnorm(n, 0, 1), each = n_periods) + time_fe <- rep(seq(0, 1, length.out = n_periods), times = n) + noise <- rnorm(n * n_periods, 0, 0.5) + treated_g3 <- (unit_ids <= n_g3) & (time_ids >= 3L) + treated_g5 <- (unit_ids > n_g3 & unit_ids <= n_g3 + n_g5) & (time_ids >= 5L) + outcome <- unit_fe + time_fe + noise + 1.5 * treated_g3 + 2.5 * treated_g5 + + data.frame( + unit = unit_ids, + time = time_ids, + outcome = outcome, + first_treat = first_treat_vals, + stringsAsFactors = FALSE + ) +} + +#' Construct a one-cohort panel with cluster variable +#' +#' @param n_clusters_treat Clusters among treated units +#' @param n_clusters_never Clusters among never-treated units +#' @param units_per_cluster Units per cluster +#' @param n_periods Time periods +#' @param seed RNG seed +#' @return data.frame with columns: unit, time, outcome, first_treat, cluster_id +make_panel_clustered <- function(n_clusters_treat = 5L, + n_clusters_never = 5L, + units_per_cluster = 4L, + n_periods = 5L, + seed = 77L) { + set.seed(seed) + n_treat <- n_clusters_treat * units_per_cluster + n_never <- n_clusters_never * units_per_cluster + n <- n_treat + n_never + + units <- seq_len(n) + times <- seq_len(n_periods) + unit_ids <- rep(units, each = n_periods) + time_ids <- rep(times, times = n) + + cluster_ids <- c( + rep(seq_len(n_clusters_treat), each = units_per_cluster * n_periods), + rep(seq_len(n_clusters_never) + n_clusters_treat, each = units_per_cluster * n_periods) + ) + + first_treat_vals <- c(rep(3L, n_treat * n_periods), + rep(Inf, n_never * n_periods)) + + cluster_fe <- rep(rnorm(n_clusters_treat + n_clusters_never, 0, 0.8), + each = units_per_cluster * n_periods) + unit_fe <- rep(rnorm(n, 0, 0.3), each = n_periods) + noise <- rnorm(n * n_periods, 0, 0.2) + treated_post <- (unit_ids <= n_treat) & (time_ids >= 3L) + outcome <- cluster_fe + unit_fe + noise + 1.8 * treated_post + + data.frame( + unit = unit_ids, + time = time_ids, + outcome = outcome, + first_treat = first_treat_vals, + cluster_id = cluster_ids, + stringsAsFactors = FALSE + ) +} + +#' Minimal two-period, two-group panel (1 treated, 1 never-treated unit) +make_degenerate_panel <- function() { + data.frame( + unit = c(1, 1, 2, 2), + time = c(1, 2, 1, 2), + outcome = c(0.5, 1.2, 0.3, 0.4), + first_treat = c(2, 2, Inf, Inf), + stringsAsFactors = FALSE + ) +} diff --git a/tests/testthat/test-edid-aggregate.R b/tests/testthat/test-edid-aggregate.R new file mode 100644 index 0000000..45390f8 --- /dev/null +++ b/tests/testthat/test-edid-aggregate.R @@ -0,0 +1,95 @@ +library(testthat) + +# Helper: run fit_edid_cells on one-cohort panel +fit_one_cohort <- function(seed = 42, n_treat = 30, n_never = 30, n_periods = 5) { + df <- make_panel_1cohort(n_treat = n_treat, n_never = n_never, + n_periods = n_periods, seed = seed) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, + store_eif = TRUE, covariates = NULL) + list(fit = fit, panel = panel) +} + +# ============================================================ +# 7.1 aggregate_overall_edid(): basic properties +# ============================================================ +test_that("aggregate_overall_edid() returns finite ATT", { + res <- fit_one_cohort() + agg <- aggregate_overall_edid(res$fit$cells, res$fit$eif_matrix, + res$fit$cell_index, res$panel, alpha = 0.05) + expect_true(is.finite(agg$att)) +}) + +test_that("aggregate_overall_edid() ATT is within [-10, 10] for ATT=2 DGP", { + res <- fit_one_cohort(seed = 42, n_treat = 50, n_never = 50) + agg <- aggregate_overall_edid(res$fit$cells, res$fit$eif_matrix, + res$fit$cell_index, res$panel, alpha = 0.05) + expect_true(agg$att > -10 && agg$att < 10) +}) + +test_that("aggregate_overall_edid() SE is positive and finite", { + res <- fit_one_cohort() + agg <- aggregate_overall_edid(res$fit$cells, res$fit$eif_matrix, + res$fit$cell_index, res$panel, alpha = 0.05) + expect_true(is.finite(agg$se)) + expect_true(agg$se > 0) +}) + +test_that("aggregate_overall_edid() EIF aggregated vector has zero mean", { + res <- fit_one_cohort() + agg <- aggregate_overall_edid(res$fit$cells, res$fit$eif_matrix, + res$fit$cell_index, res$panel, alpha = 0.05) + expect_equal(mean(agg$eif_agg), 0, tolerance = 1e-8) +}) + +# ============================================================ +# 7.2 aggregate_event_study_edid(): structure +# ============================================================ +test_that("aggregate_event_study_edid() returns a list with entries for each relative time", { + res <- fit_one_cohort() + es <- aggregate_event_study_edid(res$fit$cells, res$fit$eif_matrix, + res$fit$cell_index, res$panel, alpha = 0.05) + # Should have entries for each unique e = t - g in the cells + expect_true(is.list(es)) + expect_true(length(es) >= 1) + for (entry in es) { + expect_true(is.finite(entry$att)) + expect_true(is.finite(entry$se)) + } +}) + +# ============================================================ +# 7.3 aggregate_group_edid(): equal-time weights +# ============================================================ +test_that("aggregate_group_edid() returns one entry per treated cohort", { + df <- make_panel_2cohort() + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, + store_eif = TRUE, covariates = NULL) + grp <- aggregate_group_edid(fit$cells, fit$eif_matrix, fit$cell_index, panel, alpha = 0.05) + expect_equal(length(grp), length(panel$treatment_groups)) + for (entry in grp) { + expect_true(is.finite(entry$att)) + } +}) + +# ============================================================ +# 7.4 WIF correction: EIF of aggregate has correct mean +# ============================================================ +test_that("compute_wif_contribution_edid() produces a length-n numeric vector", { + res <- fit_one_cohort() + wif <- compute_wif_contribution_edid( + weight_fn = function(cells, cell_idx, po) { + # simple uniform weight function for test + post_cells <- Filter(function(c) !c$is_pre && !is.na(c$att), cells) + n_post <- length(post_cells) + setNames(rep(1/n_post, n_post), seq_len(n_post)) + }, + cells = res$fit$cells, + eif_matrix = res$fit$eif_matrix, + cell_index = res$fit$cell_index, + panel_obj = res$panel + ) + expect_equal(length(wif), res$panel$n) + expect_true(is.numeric(wif)) +}) diff --git a/tests/testthat/test-edid-bootstrap.R b/tests/testthat/test-edid-bootstrap.R new file mode 100644 index 0000000..e234385 --- /dev/null +++ b/tests/testthat/test-edid-bootstrap.R @@ -0,0 +1,137 @@ +library(testthat) + +# ============================================================ +# 8.1 generate_multiplier_weights_edid(): Rademacher +# ============================================================ +test_that("generate_multiplier_weights_edid() Rademacher: values are in {-1, +1}", { + set.seed(42) + W <- generate_multiplier_weights_edid(n = 50L, n_bootstrap = 200L, + type = "rademacher", seed = 42L) + expect_equal(dim(W), c(50L, 200L)) + unique_vals <- unique(as.vector(W)) + expect_true(all(unique_vals %in% c(-1, 1))) +}) + +test_that("generate_multiplier_weights_edid() Rademacher: roughly 50/50 split", { + set.seed(1) + W <- generate_multiplier_weights_edid(n = 1000L, n_bootstrap = 1L, + type = "rademacher", seed = 1L) + prop_pos <- mean(W == 1) + expect_true(prop_pos > 0.4 && prop_pos < 0.6) +}) + +# ============================================================ +# 8.2 generate_multiplier_weights_edid(): Mammen +# ============================================================ +test_that("generate_multiplier_weights_edid() Mammen: values are in the two Mammen values", { + set.seed(42) + W <- generate_multiplier_weights_edid(n = 100L, n_bootstrap = 100L, + type = "mammen", seed = 42L) + mammen_lo <- -(sqrt(5) - 1) / 2 + mammen_hi <- (sqrt(5) + 1) / 2 + unique_vals <- unique(as.vector(W)) + expect_true(all(abs(unique_vals - mammen_lo) < 1e-10 | + abs(unique_vals - mammen_hi) < 1e-10)) +}) + +# ============================================================ +# 8.3 generate_multiplier_weights_edid(): Webb +# ============================================================ +test_that("generate_multiplier_weights_edid() Webb: values are among 6 Webb values", { + set.seed(42) + W <- generate_multiplier_weights_edid(n = 200L, n_bootstrap = 100L, + type = "webb", seed = 42L) + webb_vals <- c(-sqrt(3/2), -1, -sqrt(1/2), sqrt(1/2), 1, sqrt(3/2)) + unique_vals <- unique(as.vector(W)) + for (v in unique_vals) { + expect_true(any(abs(v - webb_vals) < 1e-10)) + } +}) + +# ============================================================ +# 8.4 generate_multiplier_weights_edid(): cluster expansion +# ============================================================ +test_that("generate_multiplier_weights_edid() cluster: units in same cluster get identical weight", { + set.seed(42) + G <- 5L + n <- 20L # 4 units per cluster + cluster_idx <- rep(1:G, each = 4L) + W <- generate_multiplier_weights_edid(n = n, n_bootstrap = 50L, + type = "rademacher", + cluster_indices = cluster_idx, + seed = 42L) + expect_equal(dim(W), c(n, 50L)) + # All units in cluster 1 must have the same weight for each draw + for (b in seq_len(50)) { + expect_true(length(unique(W[cluster_idx == 1L, b])) == 1L) + } +}) + +# ============================================================ +# 8.5 generate_multiplier_weights_edid(): reproducibility with seed +# ============================================================ +test_that("generate_multiplier_weights_edid() is reproducible with seed", { + W1 <- generate_multiplier_weights_edid(50L, 100L, "rademacher", seed = 777L) + W2 <- generate_multiplier_weights_edid(50L, 100L, "rademacher", seed = 777L) + expect_identical(W1, W2) +}) + +# ============================================================ +# 8.6 compute_bootstrap_stats_edid(): output structure +# ============================================================ +test_that("compute_bootstrap_stats_edid() returns named list with correct fields", { + set.seed(1) + att_hat <- 1.5 + boot_draws <- rnorm(200, mean = att_hat, sd = 0.3) + res <- compute_bootstrap_stats_edid(boot_draws, att_hat, alpha = 0.05) + expect_named(res, c("se_boot", "ci_lower", "ci_upper", "p_value_boot"), + ignore.order = TRUE) +}) + +test_that("compute_bootstrap_stats_edid() SE is positive", { + set.seed(2) + att_hat <- 0.8 + boot_draws <- rnorm(500, att_hat, 0.5) + res <- compute_bootstrap_stats_edid(boot_draws, att_hat) + expect_true(res$se_boot > 0) +}) + +test_that("compute_bootstrap_stats_edid() CI lower < upper", { + set.seed(3) + att_hat <- 2.0 + boot_draws <- rnorm(200, att_hat, 0.4) + res <- compute_bootstrap_stats_edid(boot_draws, att_hat) + expect_true(res$ci_lower < res$ci_upper) +}) + +test_that("compute_bootstrap_stats_edid() p_value in [0, 1]", { + set.seed(4) + att_hat <- 0.0 + boot_draws <- rnorm(300, 0, 0.5) + res <- compute_bootstrap_stats_edid(boot_draws, att_hat) + expect_true(res$p_value_boot >= 0 && res$p_value_boot <= 1) +}) + +# ============================================================ +# 8.7 run_multiplier_bootstrap_edid(): basic smoke test +# ============================================================ +test_that("run_multiplier_bootstrap_edid() runs without error and returns bootstrap draws", { + df <- make_panel_1cohort(seed = 77) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, + store_eif = TRUE, covariates = NULL) + boot_res <- run_multiplier_bootstrap_edid( + cells = fit$cells, + eif_matrix = fit$eif_matrix, + cell_index = fit$cell_index, + panel_obj = panel, + n_bootstrap = 100L, + bootstrap_weights = "rademacher", + seed = 42L, + aggregate = "overall", + alpha = 0.05 + ) + expect_true(!is.null(boot_res$overall_b)) + expect_equal(length(boot_res$overall_b), 100L) + expect_true(all(is.finite(boot_res$overall_b))) +}) diff --git a/tests/testthat/test-edid-inference.R b/tests/testthat/test-edid-inference.R new file mode 100644 index 0000000..d25bfff --- /dev/null +++ b/tests/testthat/test-edid-inference.R @@ -0,0 +1,96 @@ +library(testthat) + +# ============================================================ +# 6.1 compute_eif_se_edid(): correct formula +# ============================================================ +test_that("compute_eif_se_edid() returns sqrt(sum(eif^2)/n^2)", { + set.seed(42) + n <- 50L + eif <- rnorm(n, 0, 1) + se <- compute_eif_se_edid(eif, n) + expected <- sqrt(sum(eif^2) / n^2) + expect_equal(se, expected, tolerance = 1e-12) +}) + +test_that("compute_eif_se_edid() returns non-negative value", { + set.seed(1) + eif <- rnorm(100) + expect_true(compute_eif_se_edid(eif, 100) >= 0) +}) + +# ============================================================ +# 6.2 cluster_aggregate_edid(): formula +# ============================================================ +test_that("cluster_aggregate_edid() sums EIF within clusters correctly", { + # 10 units, 2 clusters of 5 each + n <- 10L + G <- 2L + cluster_idx <- c(rep(1L, 5L), rep(2L, 5L)) + set.seed(1) + eif <- rnorm(n) + + result <- cluster_aggregate_edid(eif, cluster_idx) + # result is the cluster sums (not yet centered here -- tester checks dimension) + # Cluster 1 sum: + c1_sum <- sum(eif[1:5]) + c2_sum <- sum(eif[6:10]) + # The function should return a length-G vector + expect_equal(length(result), G) +}) + +test_that("cluster_aggregate_edid() SE with clustering differs from iid SE", { + df <- make_panel_clustered(seed = 42) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat", + cluster = "cluster_id") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "post") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") + w <- compute_efficient_weights_edid(omega) + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "post") + att <- sum(w * y_hat) + eif <- compute_eif_nocov_edid(3L, 4L, pairs, w, panel, att, "post") + + se_iid <- compute_eif_se_edid(eif, panel$n) + clust_agg <- cluster_aggregate_edid(eif, panel$cluster_indices) + se_cluster <- safe_inference_edid(eif, panel$cluster_indices, 0.05)$se + # Cluster SE should be finite and positive + expect_true(is.finite(se_cluster)) + expect_true(se_cluster > 0) + # Cluster SE and iid SE are generally different (not testing direction) + expect_false(isTRUE(all.equal(se_iid, se_cluster))) +}) + +# ============================================================ +# 6.3 safe_inference_edid(): output structure +# ============================================================ +test_that("safe_inference_edid() returns named list with expected fields", { + set.seed(42) + eif <- rnorm(50) + res <- safe_inference_edid(eif, cluster_indices = NULL, alpha = 0.05) + expect_named(res, c("se", "ci_lower", "ci_upper", "t_stat", "p_value", "inference_valid"), + ignore.order = TRUE) +}) + +test_that("safe_inference_edid() returns inference_valid=FALSE when EIF is all zeros", { + eif <- rep(0, 50) + res <- safe_inference_edid(eif, cluster_indices = NULL, alpha = 0.05) + expect_false(res$inference_valid) + expect_true(is.na(res$se) || res$se == 0) +}) + +test_that("safe_inference_edid() CI width is positive for non-degenerate EIF", { + set.seed(10) + eif <- rnorm(100) + res <- safe_inference_edid(eif, cluster_indices = NULL, alpha = 0.05) + ci_width <- res$ci_upper - res$ci_lower + expect_true(ci_width > 0 || !res$inference_valid) +}) + +test_that("safe_inference_edid() p_value is in [0, 1]", { + set.seed(15) + eif <- rnorm(80) + res <- safe_inference_edid(eif, cluster_indices = NULL, alpha = 0.05) + if (res$inference_valid) { + expect_true(res$p_value >= 0 && res$p_value <= 1) + } +}) diff --git a/tests/testthat/test-edid-integration.R b/tests/testthat/test-edid-integration.R new file mode 100644 index 0000000..5274473 --- /dev/null +++ b/tests/testthat/test-edid-integration.R @@ -0,0 +1,255 @@ +library(testthat) + +# ============================================================ +# 9.1 Basic edid() call returns edid_fit object +# ============================================================ +test_that("edid() returns an edid_fit object on one-cohort panel", { + df <- make_panel_1cohort(seed = 42) + fit <- edid( + data = df, + outcome = "outcome", + unit = "unit", + time = "time", + first_treat = "first_treat", + pt_assumption = "all", + aggregate = "all", + n_bootstrap = 0L + ) + expect_s3_class(fit, "edid_fit") +}) + +# ============================================================ +# 9.2 edid_fit object fields +# ============================================================ +test_that("edid_fit contains all required top-level fields", { + df <- make_panel_1cohort(seed = 1) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "all", aggregate = "all", n_bootstrap = 0L) + required_fields <- c("call", "pt_assumption", "control_group", "alpha", "n", + "T_periods", "treatment_groups", "anticipation", "inference_type", + "cells", "att_gt", "overall", "event_study", "group") + for (f in required_fields) { + expect_true(f %in% names(fit), + info = paste("Missing field:", f)) + } +}) + +# ============================================================ +# 9.3 att_gt data.frame structure +# ============================================================ +test_that("edid_fit$att_gt is a data.frame with required columns", { + df <- make_panel_1cohort(seed = 2) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + aggregate = "all", n_bootstrap = 0L) + expect_s3_class(fit$att_gt, "data.frame") + expected_cols <- c("group", "time", "att", "se", "ci_lower", "ci_upper", "p_value", "is_pre") + for (col in expected_cols) { + expect_true(col %in% names(fit$att_gt), info = paste("Missing column:", col)) + } +}) + +# ============================================================ +# 9.4 ATT estimates are finite for post-treatment cells +# ============================================================ +test_that("edid() post-treatment ATT estimates are finite", { + df <- make_panel_1cohort(seed = 3) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + aggregate = "all", n_bootstrap = 0L) + post_cells <- fit$att_gt[!fit$att_gt$is_pre, ] + expect_true(all(is.finite(post_cells$att))) +}) + +# ============================================================ +# 9.5 PT-Post: ATT close to true value of 2 (large sample) +# ============================================================ +test_that("edid() PT-Post overall ATT close to 2 for ATT=2 DGP (large sample)", { + df <- make_panel_1cohort(n_treat = 300, n_never = 300, n_periods = 5, seed = 555) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", + aggregate = "overall", + n_bootstrap = 0L) + # True ATT = 2; allow generous tolerance for finite samples + expect_equal(fit$overall$att, 2, tolerance = 0.4) +}) + +test_that("edid() PT-All overall ATT close to 2 for ATT=2 DGP (large sample)", { + df <- make_panel_1cohort(n_treat = 300, n_never = 300, n_periods = 5, seed = 666) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "all", + aggregate = "overall", + n_bootstrap = 0L) + expect_equal(fit$overall$att, 2, tolerance = 0.5) +}) + +# ============================================================ +# 9.6 S3 methods work without error +# ============================================================ +test_that("print.edid_fit() runs without error", { + df <- make_panel_1cohort(seed = 4) + fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + expect_output(print(fit)) +}) + +test_that("summary.edid_fit() runs without error", { + df <- make_panel_1cohort(seed = 5) + fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + expect_output(summary(fit)) +}) + +test_that("coef.edid_fit() returns named numeric vector for att_gt", { + df <- make_panel_1cohort(seed = 6) + fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + coefs <- coef(fit, which = "att_gt") + expect_true(is.numeric(coefs)) + expect_true(length(coefs) > 0) + expect_false(is.null(names(coefs))) +}) + +test_that("vcov.edid_fit() returns a numeric matrix", { + df <- make_panel_1cohort(seed = 7, n_treat = 40, n_never = 40) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + aggregate = "all", store_eif = TRUE) + V <- vcov(fit, which = "att_gt") + expect_true(is.matrix(V)) + expect_true(is.numeric(V)) +}) + +test_that("as.data.frame.edid_fit() returns a data.frame", { + df <- make_panel_1cohort(seed = 8) + fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + df_out <- as.data.frame(fit) + expect_s3_class(df_out, "data.frame") +}) + +# ============================================================ +# 9.7 Two-cohort staggered panel +# ============================================================ +test_that("edid() two-cohort staggered panel produces two groups in group aggregation", { + df <- make_panel_2cohort(seed = 200) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "all", aggregate = "all", n_bootstrap = 0L) + expect_equal(length(fit$group), 2L) +}) + +test_that("edid() two-cohort: group ATTs are near true values 1.5 and 2.5 (large sample)", { + df <- make_panel_2cohort(n_g3 = 200, n_g5 = 200, n_never = 200, + n_periods = 7, seed = 300) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", aggregate = "group", n_bootstrap = 0L) + atts <- sapply(fit$group, function(x) x$att) + # Group g=3 should be near 1.5; group g=5 near 2.5 + expect_equal(unname(sort(atts)), c(1.5, 2.5), tolerance = 0.6) +}) + +# ============================================================ +# 9.8 Bootstrap integration +# ============================================================ +test_that("edid() with n_bootstrap > 0 returns bootstrap field in edid_fit", { + df <- make_panel_1cohort(seed = 42) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", aggregate = "overall", + n_bootstrap = 50L, bootstrap_weights = "rademacher", + seed = 42L) + expect_false(is.null(fit$bootstrap)) + expect_equal(fit$bootstrap$n_bootstrap, 50L) +}) + +test_that("edid() bootstrap SE differs from analytical SE (not identical)", { + df <- make_panel_1cohort(n_treat = 40, n_never = 40, seed = 99) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", aggregate = "overall", + n_bootstrap = 200L, seed = 42L) + # Bootstrap SE and analytical SE are related but not identical + # Both should be finite and positive + expect_true(is.finite(fit$overall$se)) + expect_true(fit$overall$se > 0) +}) + +# ============================================================ +# 9.9 Clustered edid() +# ============================================================ +test_that("edid() with cluster argument produces finite clustered SEs", { + df <- make_panel_clustered(seed = 55) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + cluster = "cluster_id", + pt_assumption = "post", aggregate = "overall", + n_bootstrap = 0L) + expect_true(is.finite(fit$overall$se)) + expect_true(fit$overall$se > 0) +}) + +# ============================================================ +# 9.10 Covariates stub +# ============================================================ +test_that("edid() errors with clear message when covariates are supplied", { + df <- make_panel_1cohort(seed = 1) + df$x1 <- rnorm(nrow(df)) + expect_error( + edid(df, "outcome", "unit", "time", "first_treat", + covariates = "x1"), + regexp = "covariate|not yet implemented" + ) +}) + +# ============================================================ +# 9.11 survey_design stub +# ============================================================ +test_that("edid() errors with clear message when survey_design is supplied", { + df <- make_panel_1cohort(seed = 1) + expect_error( + edid(df, "outcome", "unit", "time", "first_treat", + survey_design = list(fake = TRUE)), + regexp = "survey|not yet implemented" + ) +}) + +# ============================================================ +# 9.12 store_eif = TRUE stores the EIF matrix +# ============================================================ +test_that("edid() with store_eif=TRUE returns eif matrix of correct dimensions", { + df <- make_panel_1cohort(n_treat = 20, n_never = 20, n_periods = 4, seed = 42) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + store_eif = TRUE, aggregate = "all") + expect_false(is.null(fit$eif)) + # eif should be n x n_non_na_cells matrix + expect_equal(nrow(fit$eif), fit$n) + expect_true(ncol(fit$eif) >= 1) +}) + +# ============================================================ +# 9.13 Degenerate panel: minimal 2-period, 2-unit case +# ============================================================ +test_that("edid() on minimal degenerate panel runs without error", { + df <- make_degenerate_panel() + # PT-Post, g=2: baseline = 2-1-0 = 1 = period_1, so all cells have no valid pairs -> NA ATT + # Should return result without error (all NA cells) + expect_no_error({ + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", aggregate = "none") + }) +}) + +# ============================================================ +# 9.14 Balanced panel enforcement +# ============================================================ +test_that("edid() errors loudly on unbalanced panel", { + df <- make_panel_1cohort(seed = 1) + df <- df[-1, ] # remove one row -> unbalanced + expect_error( + edid(df, "outcome", "unit", "time", "first_treat"), + regexp = "balanced|unbalanced" + ) +}) + +# ============================================================ +# 9.15 Inference: CI contains true value in reasonable proportion (large n sanity check) +# ============================================================ +test_that("edid() 95% CI contains 2 for large-n ATT=2 DGP", { + df <- make_panel_1cohort(n_treat = 500, n_never = 500, n_periods = 5, seed = 1234) + fit <- edid(df, "outcome", "unit", "time", "first_treat", + pt_assumption = "post", aggregate = "overall", n_bootstrap = 0L) + ci_lo <- fit$overall$ci_lower + ci_hi <- fit$overall$ci_upper + expect_true(ci_lo < 2 && ci_hi > 2, + info = paste("CI:", ci_lo, "-", ci_hi, "does not contain 2")) +}) diff --git a/tests/testthat/test-edid-nocov.R b/tests/testthat/test-edid-nocov.R new file mode 100644 index 0000000..a90c636 --- /dev/null +++ b/tests/testthat/test-edid-nocov.R @@ -0,0 +1,178 @@ +library(testthat) + +# ============================================================ +# 5.1 compute_omega_star_nocov_edid(): return type and dimensions +# ============================================================ +test_that("compute_omega_star_nocov_edid() returns H x H symmetric numeric matrix", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 1) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + H <- nrow(pairs) + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + expect_true(is.matrix(omega)) + expect_equal(dim(omega), c(H, H)) + expect_true(isSymmetric(omega, tol = 1e-10)) +}) + +test_that("compute_omega_star_nocov_edid() is positive semi-definite (eigenvalues >= 0)", { + df <- make_panel_1cohort(n_treat = 40, n_never = 40, n_periods = 5, seed = 2) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + eigs <- eigen(omega, symmetric = TRUE, only.values = TRUE)$values + expect_true(all(eigs >= -1e-10)) # PSD up to numerical noise +}) + +# ============================================================ +# 5.2 compute_omega_star_nocov_edid(): PT-Post returns 1x1 matrix +# ============================================================ +test_that("compute_omega_star_nocov_edid() returns 1x1 matrix under PT-Post", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 3) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "post") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") + expect_equal(dim(omega), c(1L, 1L)) + # The 1x1 Omega* must be positive (variance is non-negative) + expect_true(omega[1, 1] >= 0) +}) + +# ============================================================ +# 5.3 compute_efficient_weights_edid(): properties +# ============================================================ +test_that("compute_efficient_weights_edid() weights sum to 1", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 4) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + w <- compute_efficient_weights_edid(omega) + expect_equal(sum(w), 1, tolerance = 1e-10) + expect_equal(length(w), nrow(pairs)) +}) + +test_that("compute_efficient_weights_edid() returns w=1 for a single pair (H=1)", { + # Construct a 1x1 omega_star + omega_1x1 <- matrix(0.5) + w <- compute_efficient_weights_edid(omega_1x1) + expect_equal(w, 1.0, tolerance = 1e-12) +}) + +test_that("compute_efficient_weights_edid() returns uniform weights when Omega* is all zeros", { + H <- 4L + omega_zero <- matrix(0, H, H) + w <- compute_efficient_weights_edid(omega_zero) + expect_equal(w, rep(1/H, H), tolerance = 1e-12) +}) + +test_that("compute_efficient_weights_edid() uses pseudoinverse fallback for singular Omega*", { + # Singular 2x2 omega (rank 1) + v <- c(1, 2) + omega_sing <- outer(v, v) * 0.1 + # Should not error; should return weights summing to 1 + w <- compute_efficient_weights_edid(omega_sing) + expect_equal(sum(w), 1, tolerance = 1e-8) + expect_equal(length(w), 2L) +}) + +test_that("compute_efficient_weights_edid() returns numeric vector with no NA or NaN", { + df <- make_panel_1cohort(n_treat = 25, n_never = 25, n_periods = 5, seed = 5) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + w <- compute_efficient_weights_edid(omega) + expect_true(all(is.finite(w))) +}) + +# ============================================================ +# 5.4 compute_generated_outcomes_nocov_edid(): shape and finiteness +# ============================================================ +test_that("compute_generated_outcomes_nocov_edid() returns length-H finite vector", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 6) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "all") + expect_equal(length(y_hat), nrow(pairs)) + expect_true(all(is.finite(y_hat))) +}) + +test_that("compute_generated_outcomes_nocov_edid() PT-Post returns length-1 vector", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 7) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "post") + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "post") + expect_equal(length(y_hat), 1L) +}) + +test_that("compute_generated_outcomes_nocov_edid() ATT=2 panel: generated outcome close to 2 for post period", { + # Panel with known ATT=2 (from make_panel_1cohort default) + df <- make_panel_1cohort(n_treat = 200, n_never = 200, n_periods = 5, seed = 99) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "post") + y_hat <- compute_generated_outcomes_nocov_edid(3L, 3L, pairs, panel, "post") + # With 200 treated, 200 never-treated, and true ATT=2, should be within 0.5 of 2 + expect_equal(y_hat[1], 2, tolerance = 0.5) +}) + +# ============================================================ +# 5.5 compute_eif_nocov_edid(): shape, finiteness, zero-mean +# ============================================================ +test_that("compute_eif_nocov_edid() returns length-n finite vector", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 8) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + n <- panel$n + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + w <- compute_efficient_weights_edid(omega) + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "all") + att_gt <- sum(w * y_hat) + eif <- compute_eif_nocov_edid(3L, 4L, pairs, w, panel, att_gt, "all") + expect_equal(length(eif), n) + expect_true(all(is.finite(eif))) +}) + +test_that("compute_eif_nocov_edid() has zero mean (up to numerical precision)", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 9) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + w <- compute_efficient_weights_edid(omega) + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "all") + att_gt <- sum(w * y_hat) + eif <- compute_eif_nocov_edid(3L, 4L, pairs, w, panel, att_gt, "all") + expect_equal(mean(eif), 0, tolerance = 1e-10) +}) + +test_that("compute_eif_nocov_edid() PT-Post: EIF has zero mean", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 10) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "post") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") + w <- compute_efficient_weights_edid(omega) + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "post") + att_gt <- sum(w * y_hat) + eif <- compute_eif_nocov_edid(3L, 4L, pairs, w, panel, att_gt, "post") + expect_equal(mean(eif), 0, tolerance = 1e-10) +}) + +test_that("compute_eif_nocov_edid() sum of squared EIF is positive (non-degenerate)", { + df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 11) + panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, + panel$period_1, "all") + omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") + w <- compute_efficient_weights_edid(omega) + y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "all") + att_gt <- sum(w * y_hat) + eif <- compute_eif_nocov_edid(3L, 4L, pairs, w, panel, att_gt, "all") + expect_true(sum(eif^2) > 0) +}) diff --git a/tests/testthat/test-edid-pairs.R b/tests/testthat/test-edid-pairs.R new file mode 100644 index 0000000..77f9a9b --- /dev/null +++ b/tests/testthat/test-edid-pairs.R @@ -0,0 +1,164 @@ +library(testthat) + +# Helper: consistent args for enumerate_valid_pairs_edid +default_treatment_groups <- c(3L, 5L) +default_time_periods <- 1:7 +default_period_1 <- 1L + +# ============================================================ +# 4.1 PT-Post: exactly one pair +# ============================================================ +test_that("enumerate_valid_pairs_edid() returns 1 pair under PT-Post for post-treatment period", { + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = default_treatment_groups, + time_periods = default_time_periods, + period_1 = default_period_1, + pt_assumption = "post", + anticipation = 0L, + never_treated_val = Inf + ) + expect_equal(nrow(pairs), 1L) + expect_equal(pairs$gp[1], Inf) + expect_equal(pairs$tpre[1], 2L) # g - 1 - anticipation = 3 - 1 - 0 = 2 +}) + +test_that("enumerate_valid_pairs_edid() returns 1 pair under PT-Post with anticipation=1", { + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L), + time_periods = 1:5, + period_1 = 1L, + pt_assumption = "post", + anticipation = 1L, + never_treated_val = Inf + ) + # baseline = g - 1 - anticipation = 3 - 1 - 1 = 1 = period_1 + # Since period_1 is excluded, should return 0 pairs + expect_equal(nrow(pairs), 0L) +}) + +test_that("enumerate_valid_pairs_edid() PT-Post baseline = period_1 returns 0 pairs", { + # When g - 1 - anticipation equals period_1, no valid pairs + pairs <- enumerate_valid_pairs_edid( + target_g = 2L, + treatment_groups = c(2L), + time_periods = 1:4, + period_1 = 1L, + pt_assumption = "post", + anticipation = 0L, + never_treated_val = Inf + ) + # g - 1 - 0 = 1 = period_1 -> 0 pairs + expect_equal(nrow(pairs), 0L) +}) + +# ============================================================ +# 4.2 PT-All: multiple pairs including same-cohort +# ============================================================ +test_that("enumerate_valid_pairs_edid() PT-All includes same-cohort comparisons", { + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L, 5L), + time_periods = 1:5, + period_1 = 1L, + pt_assumption = "all", + anticipation = 0L, + never_treated_val = Inf + ) + expect_true(nrow(pairs) > 1L) + # Same-cohort comparison gp=3 must be present + expect_true(any(pairs$gp == 3L)) + # Never-treated comparison gp=Inf must be present + expect_true(any(is.infinite(pairs$gp))) + # period_1 must NOT appear as tpre + expect_false(any(pairs$tpre == 1L)) +}) + +test_that("enumerate_valid_pairs_edid() PT-All excludes period_1 as tpre", { + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L), + time_periods = 1:5, + period_1 = 1L, + pt_assumption = "all", + anticipation = 0L, + never_treated_val = Inf + ) + expect_false(1L %in% pairs$tpre) +}) + +test_that("enumerate_valid_pairs_edid() PT-All with anticipation=1 adjusts gp's effective treatment", { + # gp=3 with anticipation=1: effective treatment = 3-1=2; valid tpre < 2, excl period_1=1 -> none + # gp=Inf: all periods except period_1 -> tpre = 2,3,4 + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L), + time_periods = 1:5, + period_1 = 1L, + pt_assumption = "all", + anticipation = 1L, + never_treated_val = Inf + ) + # gp=3 has no valid tpre (effective treatment = 2, only tpre < 2 excl 1 = none) + expect_false(any(pairs$gp == 3L)) + # never-treated pairs should still exist + expect_true(any(is.infinite(pairs$gp))) +}) + +# ============================================================ +# 4.3 Never-treated pairs retained +# ============================================================ +test_that("enumerate_valid_pairs_edid() PT-All includes all never-treated periods except period_1", { + time_periods <- 1:6 + period_1 <- 1L + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L), + time_periods = time_periods, + period_1 = period_1, + pt_assumption = "all", + anticipation = 0L, + never_treated_val = Inf + ) + inf_pairs <- pairs[is.infinite(pairs$gp), ] + # All periods 2..6 should appear as tpre for gp=Inf (5 periods) + expect_equal(sort(inf_pairs$tpre), 2:6) +}) + +# ============================================================ +# 4.4 Empty pairs cases +# ============================================================ +test_that("enumerate_valid_pairs_edid() returns 0 rows when target_g is first-ever cohort with period_1 baseline", { + # g=2, periods=1:4, period_1=1: PT-Post baseline = g-1-0=1 = period_1, so 0 pairs + pairs <- enumerate_valid_pairs_edid( + target_g = 2L, + treatment_groups = c(2L), + time_periods = 1:4, + period_1 = 1L, + pt_assumption = "post", + anticipation = 0L, + never_treated_val = Inf + ) + expect_equal(nrow(pairs), 0L) + expect_true(is.data.frame(pairs)) + expect_true("gp" %in% names(pairs)) + expect_true("tpre" %in% names(pairs)) +}) + +# ============================================================ +# 4.5 Return type +# ============================================================ +test_that("enumerate_valid_pairs_edid() always returns a data.frame with gp and tpre columns", { + pairs <- enumerate_valid_pairs_edid( + target_g = 3L, + treatment_groups = c(3L), + time_periods = 1:5, + period_1 = 1L, + pt_assumption = "all", + anticipation = 0L, + never_treated_val = Inf + ) + expect_s3_class(pairs, "data.frame") + expect_named(pairs, c("gp", "tpre")) +}) diff --git a/tests/testthat/test-edid-validate.R b/tests/testthat/test-edid-validate.R new file mode 100644 index 0000000..2ccba9b --- /dev/null +++ b/tests/testthat/test-edid-validate.R @@ -0,0 +1,265 @@ +library(testthat) +# helper-edid.R is auto-loaded + +# ============================================================ +# 3.1 Valid inputs pass without error +# ============================================================ +test_that("validate_edid_inputs() passes on valid one-cohort panel", { + df <- make_panel_1cohort() + expect_silent( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ) + ) +}) + +test_that("validate_edid_inputs() passes on two-cohort panel", { + df <- make_panel_2cohort() + expect_silent( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "post", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 100L, anticipation = 0L, survey_design = NULL + ) + ) +}) + +# ============================================================ +# 3.2 Missing column names +# ============================================================ +test_that("validate_edid_inputs() errors on missing outcome column", { + df <- make_panel_1cohort() + expect_error( + validate_edid_inputs( + data = df, outcome = "y_outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "y_outcome" + ) +}) + +test_that("validate_edid_inputs() errors on missing time column", { + df <- make_panel_1cohort() + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "t_var", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "t_var" + ) +}) + +# ============================================================ +# 3.3 Non-numeric outcome +# ============================================================ +test_that("validate_edid_inputs() errors on character outcome column", { + df <- make_panel_1cohort() + df$outcome <- as.character(df$outcome) + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ) + ) +}) + +# ============================================================ +# 3.4 Non-finite outcomes +# ============================================================ +test_that("validate_edid_inputs() errors on Inf outcome", { + df <- make_panel_1cohort() + df$outcome[1] <- Inf + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "finite|non-finite|Inf" + ) +}) + +test_that("validate_edid_inputs() errors on NA outcome", { + df <- make_panel_1cohort() + df$outcome[5] <- NA_real_ + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ) + ) +}) + +# ============================================================ +# 3.5 Unbalanced panel +# ============================================================ +test_that("validate_edid_inputs() errors on unbalanced panel", { + df <- make_panel_1cohort() + df_unbal <- df[-1, ] # drop one row -> unit 1 missing period 1 + expect_error( + validate_edid_inputs( + data = df_unbal, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "balanced|unbalanced" + ) +}) + +# ============================================================ +# 3.6 Duplicate (unit, time) rows +# ============================================================ +test_that("validate_edid_inputs() errors on duplicate (unit, time) rows", { + df <- make_panel_1cohort() + df_dup <- rbind(df, df[1, ]) # duplicate first row + expect_error( + validate_edid_inputs( + data = df_dup, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "[Dd]uplicate" + ) +}) + +# ============================================================ +# 3.7 Non-absorbing treatment +# ============================================================ +test_that("validate_edid_inputs() errors on non-absorbing treatment", { + df <- make_panel_1cohort() + # Make first_treat time-varying within unit 1 + df$first_treat[df$unit == 1 & df$time == 2] <- 4L + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "absorbing|time-varying|constant" + ) +}) + +# ============================================================ +# 3.8 No never-treated units +# ============================================================ +test_that("validate_edid_inputs() errors when no never-treated units and control_group='never_treated'", { + df <- make_panel_1cohort() + # relabel all never-treated as cohort 4 + df$first_treat[df$first_treat == Inf] <- 4L + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "never.treated|never_treated" + ) +}) + +# ============================================================ +# 3.9 Covariate stub +# ============================================================ +test_that("validate_edid_inputs() errors when covariates supplied (stub)", { + df <- make_panel_1cohort() + df$x1 <- rnorm(nrow(df)) + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = "x1", pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "covariate|not yet implemented" + ) +}) + +# ============================================================ +# 3.10 Survey stub +# ============================================================ +test_that("validate_edid_inputs() errors when survey_design supplied (stub)", { + df <- make_panel_1cohort() + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, + survey_design = list(strata = "fake") + ), + regexp = "survey|not yet implemented" + ) +}) + +# ============================================================ +# 3.11 Invalid alpha +# ============================================================ +test_that("validate_edid_inputs() errors on alpha outside (0,1)", { + df <- make_panel_1cohort() + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 1.5, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ) + ) + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0, cluster = NULL, control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ) + ) +}) + +# ============================================================ +# 3.12 Cluster column time-varying check +# ============================================================ +test_that("validate_edid_inputs() errors on time-varying cluster variable", { + df <- make_panel_clustered() + # Make cluster_id time-varying for unit 1 + df$cluster_id[df$unit == 1 & df$time == 2] <- 999L + expect_error( + validate_edid_inputs( + data = df, outcome = "outcome", unit = "unit", + time = "time", first_treat = "first_treat", + covariates = NULL, pt_assumption = "all", + alpha = 0.05, cluster = "cluster_id", control_group = "never_treated", + n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + ), + regexp = "cluster|time.invariant|time-invariant" + ) +}) From e4fe95deae857dbd188d9fd13bef33e6f76686d4 Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Mon, 13 Apr 2026 15:27:32 -0400 Subject: [PATCH 05/12] Align edid() arguments with att_gt() conventions and add aggte_edid() - Rename edid() args: outcome->yname, unit->idname, time->tname, first_treat->gname, alpha->alp, cluster->clustervars, n_bootstrap->bstrap+biters; control_group "never_treated"->"nevertreated" - Add G=0->Inf auto-conversion so att_gt() datasets work directly - Rewrite print.edid_fit() to MP-style ATT(g,t) table with sig codes - summary.edid_fit() delegates to print then appends overall/ES/group - Add bstrap field to edid_fit object for CI label selection - Create R/edid-aggte.R: aggte_edid(), print/summary.AGGTEobj_edid - Update compare_att_gt_edid.R: new arg names, drop G_edid column - Update all edid test files to use renamed arguments Co-Authored-By: Claude Sonnet 4.6 --- NAMESPACE | 3 + R/edid-aggte.R | 270 +++++++++++++++++++++++++ R/edid-data.R | 54 ++--- R/edid-methods.R | 108 ++++++---- R/edid-validate.R | 125 ++++++------ R/edid.R | 129 +++++++----- compare_att_gt_edid.R | 216 ++++++++++++++++++++ man/aggte_edid.Rd | 56 +++++ man/build_cluster_index.Rd | 6 +- man/edid.Rd | 62 +++--- man/prepare_edid_panel.Rd | 24 +-- man/print.AGGTEobj_edid.Rd | 20 ++ man/print.edid_fit.Rd | 3 +- man/summary.AGGTEobj_edid.Rd | 19 ++ man/summary.edid_fit.Rd | 3 +- man/validate_edid_inputs.Rd | 28 +-- tests/testthat/test-edid-aggregate.R | 6 +- tests/testthat/test-edid-bootstrap.R | 3 +- tests/testthat/test-edid-inference.R | 5 +- tests/testthat/test-edid-integration.R | 123 ++++++----- tests/testthat/test-edid-nocov.R | 36 ++-- tests/testthat/test-edid-validate.R | 142 ++++++------- 22 files changed, 1064 insertions(+), 377 deletions(-) create mode 100644 R/edid-aggte.R create mode 100644 compare_att_gt_edid.R create mode 100644 man/aggte_edid.Rd create mode 100644 man/print.AGGTEobj_edid.Rd create mode 100644 man/summary.AGGTEobj_edid.Rd diff --git a/NAMESPACE b/NAMESPACE index 4da7c52..2db2ec6 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,9 +9,11 @@ S3method(glance,MP) S3method(nobs,AGGTEobj) S3method(nobs,MP) S3method(print,AGGTEobj) +S3method(print,AGGTEobj_edid) S3method(print,MP) S3method(print,edid_fit) S3method(summary,AGGTEobj) +S3method(summary,AGGTEobj_edid) S3method(summary,MP) S3method(summary,MP.TEST) S3method(summary,edid_fit) @@ -23,6 +25,7 @@ export(DIDparams) export(MP) export(MP.TEST) export(aggte) +export(aggte_edid) export(att_gt) export(build_sim_dataset) export(compute.aggte) diff --git a/R/edid-aggte.R b/R/edid-aggte.R new file mode 100644 index 0000000..f564b98 --- /dev/null +++ b/R/edid-aggte.R @@ -0,0 +1,270 @@ +# edid-aggte.R +# Aggregation function for edid_fit objects, mirroring the aggte() interface. + +#' Aggregate edid_fit estimates +#' +#' Provides the same user-facing interface as \code{\link[did]{aggte}} but +#' accepts an \code{edid_fit} object produced by \code{\link{edid}}. +#' +#' @param edid_fit_obj An \code{edid_fit} object returned by \code{edid()}. +#' @param type Character scalar: aggregation type. One of +#' \code{"simple"} (overall ATT), \code{"dynamic"} (event-study), +#' \code{"group"} (cohort-level ATT), or \code{"calendar"} (not implemented). +#' @param balance_e Integer or \code{NULL}: if not \code{NULL}, restricts the +#' dynamic aggregation to relative times in +#' \eqn{[-\text{balance\_e}, \text{balance\_e}]}. +#' @param min_e Numeric: minimum relative time to include in dynamic output. +#' Default \code{-Inf}. +#' @param max_e Numeric: maximum relative time to include in dynamic output. +#' Default \code{Inf}. +#' @param na.rm Logical: whether to remove NA ATT entries before aggregating. +#' Default \code{FALSE}. +#' +#' @return An S3 object of class \code{c("AGGTEobj_edid", "list")} with fields +#' matching \code{AGGTEobj} where possible: +#' \describe{ +#' \item{\code{att.egt}}{Vector of ATT estimates for each index.} +#' \item{\code{se.egt}}{Vector of standard errors.} +#' \item{\code{egt}}{Vector of indices (relative time, group, etc.).} +#' \item{\code{type}}{The aggregation type string.} +#' \item{\code{overall.att}}{Scalar overall ATT.} +#' \item{\code{overall.se}}{Scalar overall SE.} +#' \item{\code{alp}}{Significance level used.} +#' \item{\code{call}}{The matched call.} +#' } +#' +#' @seealso \code{\link{edid}}, \code{\link[did]{aggte}} +#' @export +aggte_edid <- function( + edid_fit_obj, + type = c("simple", "dynamic", "group", "calendar"), + balance_e = NULL, + min_e = -Inf, + max_e = Inf, + na.rm = FALSE +) { + mc <- match.call() + type <- match.arg(type) + + if (!inherits(edid_fit_obj, "edid_fit")) { + stop("`edid_fit_obj` must be an object of class `edid_fit` returned by edid().") + } + + alp <- edid_fit_obj$alpha + + # Helper: extract overall ATT + SE from the edid_fit object + .get_overall <- function(obj) { + ov <- obj$overall + att <- if (!is.null(ov)) ov$att else NA_real_ + se <- if (!is.null(ov)) ov$se else NA_real_ + list(att = att, se = se) + } + + if (type == "calendar") { + stop("aggte_edid() does not support type = \"calendar\". ", + "edid() does not compute calendar-time treatment effects.") + } + + # ------------------------------------------------------------------ + # simple: return overall ATT already computed + # ------------------------------------------------------------------ + if (type == "simple") { + ov_info <- .get_overall(edid_fit_obj) + out <- list( + att.egt = ov_info$att, + se.egt = ov_info$se, + egt = NA_real_, + type = type, + overall.att = ov_info$att, + overall.se = ov_info$se, + alp = alp, + call = mc + ) + class(out) <- c("AGGTEobj_edid", "list") + return(out) + } + + # ------------------------------------------------------------------ + # dynamic: event-study, filter by min_e / max_e / balance_e + # ------------------------------------------------------------------ + if (type == "dynamic") { + es_list <- edid_fit_obj$event_study + if (is.null(es_list) || length(es_list) == 0L) { + stop("No event-study results in edid_fit_obj. ", + "Re-run edid() with aggregate = \"event_study\" or \"all\".") + } + + # Convert to flat vectors + e_vals <- vapply(es_list, function(x) x$e, numeric(1L)) + att_vec <- vapply(es_list, function(x) x$att, numeric(1L)) + se_vec <- vapply(es_list, function(x) x$se, numeric(1L)) + + # Apply balance_e filter first (symmetric window) + if (!is.null(balance_e)) { + keep_bal <- (e_vals >= -balance_e) & (e_vals <= balance_e) + e_vals <- e_vals[keep_bal] + att_vec <- att_vec[keep_bal] + se_vec <- se_vec[keep_bal] + } + + # Apply min_e / max_e filter + keep_range <- (e_vals >= min_e) & (e_vals <= max_e) + e_vals <- e_vals[keep_range] + att_vec <- att_vec[keep_range] + se_vec <- se_vec[keep_range] + + # Optionally drop NAs + if (na.rm) { + keep_na <- !is.na(att_vec) + e_vals <- e_vals[keep_na] + att_vec <- att_vec[keep_na] + se_vec <- se_vec[keep_na] + } + + ov_info <- .get_overall(edid_fit_obj) + out <- list( + att.egt = att_vec, + se.egt = se_vec, + egt = e_vals, + type = type, + overall.att = ov_info$att, + overall.se = ov_info$se, + alp = alp, + call = mc + ) + class(out) <- c("AGGTEobj_edid", "list") + return(out) + } + + # ------------------------------------------------------------------ + # group: cohort-level ATTs + # ------------------------------------------------------------------ + if (type == "group") { + gr_list <- edid_fit_obj$group + if (is.null(gr_list) || length(gr_list) == 0L) { + stop("No group results in edid_fit_obj. ", + "Re-run edid() with aggregate = \"group\" or \"all\".") + } + + g_vals <- vapply(gr_list, function(x) x$group, numeric(1L)) + att_vec <- vapply(gr_list, function(x) x$att, numeric(1L)) + se_vec <- vapply(gr_list, function(x) x$se, numeric(1L)) + + if (na.rm) { + keep_na <- !is.na(att_vec) + g_vals <- g_vals[keep_na] + att_vec <- att_vec[keep_na] + se_vec <- se_vec[keep_na] + } + + ov_info <- .get_overall(edid_fit_obj) + out <- list( + att.egt = att_vec, + se.egt = se_vec, + egt = g_vals, + type = type, + overall.att = ov_info$att, + overall.se = ov_info$se, + alp = alp, + call = mc + ) + class(out) <- c("AGGTEobj_edid", "list") + return(out) + } +} + +#' Print method for AGGTEobj_edid objects +#' +#' Prints aggregated treatment effects in a format similar to +#' \code{print.AGGTEobj}. +#' +#' @param x an \code{AGGTEobj_edid} object +#' @param ... additional arguments (currently ignored) +#' +#' @return \code{x} invisibly +#' @export +print.AGGTEobj_edid <- function(x, ...) { + cat("\n") + cat("Call:\n") + print(x$call) + cat("\n") + + alp <- x$alp + pointwise_cval <- stats::qnorm(1 - alp / 2) + + # Overall ATT summary + ov_att <- x$overall.att + ov_se <- x$overall.se + if (!is.null(ov_att) && !is.na(ov_att)) { + ov_lo <- ov_att - pointwise_cval * ov_se + ov_hi <- ov_att + pointwise_cval * ov_se + ov_sig <- (ov_hi < 0) | (ov_lo > 0) + if (is.na(ov_sig)) ov_sig <- FALSE + ov_sig_text <- if (ov_sig) "*" else "" + + if (x$type == "dynamic") { + cat("Overall summary of ATT's based on event-study/dynamic aggregation: \n") + } else if (x$type == "group") { + cat("Overall summary of ATT's based on group/cohort aggregation: \n") + } else { + cat("Overall ATT: \n") + } + + out1 <- cbind.data.frame(round(ov_att, 4), round(ov_se, 4), + round(ov_lo, 4), round(ov_hi, 4), + ov_sig_text) + colnames(out1) <- c("ATT", " Std. Error", + paste0(" [ ", 100 * (1 - alp), "% "), + "Conf. Int.]", "") + print(out1, row.names = FALSE) + cat("\n\n") + } + + # Per-index table for dynamic / group + if (x$type %in% c("dynamic", "group")) { + if (x$type == "dynamic") { + c1name <- "Event time" + cat("Dynamic Effects:\n") + } else { + c1name <- "Group" + cat("Group Effects:\n") + } + + cband_text1 <- paste0("[", 100 * (1 - alp), "% Pointwise ") + + cband_lower <- x$att.egt - pointwise_cval * x$se.egt + cband_upper <- x$att.egt + pointwise_cval * x$se.egt + + sig <- (cband_upper < 0) | (cband_lower > 0) + sig[is.na(sig)] <- FALSE + sig_text <- ifelse(sig, "*", "") + + out2 <- cbind.data.frame(x$egt, x$att.egt, x$se.egt, cband_lower, cband_upper) + out2 <- round(out2, 4) + out2 <- cbind.data.frame(out2, sig_text) + colnames(out2) <- c(c1name, "Estimate", "Std. Error", + cband_text1, "Conf. Band]", "") + print(out2, row.names = FALSE, justify = "centre") + } + + cat("---\n") + cat("Signif. codes: `*' confidence band does not cover 0") + cat("\n\n") + cat("Estimation Method: Efficient DiD (Chen, Sant'Anna & Xie 2025)\n") + + invisible(x) +} + +#' Summary method for AGGTEobj_edid objects +#' +#' Delegates to \code{print.AGGTEobj_edid}. +#' +#' @param object an \code{AGGTEobj_edid} object +#' @param ... additional arguments (currently ignored) +#' +#' @return \code{object} invisibly +#' @export +summary.AGGTEobj_edid <- function(object, ...) { + print.AGGTEobj_edid(object, ...) + invisible(object) +} diff --git a/R/edid-data.R b/R/edid-data.R index 8b634d4..835640d 100644 --- a/R/edid-data.R +++ b/R/edid-data.R @@ -7,21 +7,21 @@ #' builds all masks and maps needed by downstream functions. #' #' @param data data.frame (or data.table / tibble) already validated -#' @param outcome character scalar: outcome column name -#' @param unit character scalar: unit id column name -#' @param time character scalar: time column name -#' @param first_treat character scalar: first-treatment-period column name +#' @param yname character scalar: outcome column name +#' @param idname character scalar: unit id column name +#' @param tname character scalar: time column name +#' @param gname character scalar: first-treatment-period column name #' @param covariates NULL (stub) -#' @param cluster character scalar or NULL -#' @param control_group \code{"never_treated"} or \code{"last_cohort"} +#' @param clustervars character scalar or NULL +#' @param control_group \code{"nevertreated"} or \code{"last_cohort"} #' @param anticipation non-negative integer #' #' @return a \code{panel_obj} list; see spec Section 5.1 #' @keywords internal prepare_edid_panel <- function( - data, outcome, unit, time, first_treat, - covariates = NULL, cluster = NULL, - control_group = "never_treated", + data, yname, idname, tname, gname, + covariates = NULL, clustervars = NULL, + control_group = "nevertreated", anticipation = 0L ) { @@ -29,13 +29,13 @@ prepare_edid_panel <- function( # 1. Coerce to data.table and sort # ----------------------------------------------------------------------- dt <- data.table::as.data.table(data) - data.table::setkeyv(dt, c(unit, time)) + data.table::setkeyv(dt, c(idname, tname)) # ----------------------------------------------------------------------- # 2-3. Extract sorted unique ids and time periods # ----------------------------------------------------------------------- - all_units <- sort(unique(dt[[unit]])) - time_periods <- sort(unique(dt[[time]])) + all_units <- sort(unique(dt[[idname]])) + time_periods <- sort(unique(dt[[tname]])) n <- length(all_units) T_periods <- length(time_periods) @@ -54,12 +54,12 @@ prepare_edid_panel <- function( # ----------------------------------------------------------------------- wide_dt <- data.table::dcast( dt, - formula = stats::as.formula(paste(unit, "~ ", time)), - value.var = outcome + formula = stats::as.formula(paste(idname, "~ ", tname)), + value.var = yname ) # Ensure rows in same order as all_units setattr <- function(x, nm, val) { attr(x, nm) <- val; x } - unit_order <- match(all_units, wide_dt[[unit]]) + unit_order <- match(all_units, wide_dt[[idname]]) wide_dt <- wide_dt[unit_order, ] # Drop the unit id column; keep only the T_periods outcome columns @@ -70,12 +70,12 @@ prepare_edid_panel <- function( colnames(outcome_wide) <- col_order # ----------------------------------------------------------------------- - # 6. unit_cohorts: first_treat value per unit (Inf for never-treated) + # 6. unit_cohorts: gname value per unit (Inf for never-treated) # ----------------------------------------------------------------------- - # Extract one first_treat per unit using base R tapply (avoids data.table NSE) - ft_vals <- dt[[first_treat]] - unit_id_vals <- dt[[unit]] - # Get first value of first_treat per unit (treatment is constant within unit) + # Extract one gname per unit using base R tapply (avoids data.table NSE) + ft_vals <- dt[[gname]] + unit_id_vals <- dt[[idname]] + # Get first value of gname per unit (treatment is constant within unit) unit_ft_map <- tapply(ft_vals, unit_id_vals, function(x) x[1L]) # Map to all_units order unit_cohorts <- as.numeric(unit_ft_map[match(all_units, names(unit_ft_map))]) @@ -134,8 +134,8 @@ prepare_edid_panel <- function( # ----------------------------------------------------------------------- cluster_indices <- NULL n_clusters <- NULL - if (!is.null(cluster)) { - cluster_indices <- build_cluster_index(dt, unit, cluster, all_units) + if (!is.null(clustervars)) { + cluster_indices <- build_cluster_index(dt, idname, clustervars, all_units) n_clusters <- length(unique(cluster_indices)) } @@ -168,16 +168,16 @@ prepare_edid_panel <- function( #' Build cluster integer index from cluster id column #' #' @param dt data.table (long format), sorted by unit then time -#' @param unit character scalar: unit id column name -#' @param cluster character scalar: cluster id column name +#' @param idname character scalar: unit id column name +#' @param clustervars character scalar: cluster id column name #' @param all_units sorted vector of unique unit ids #' #' @return integer vector length n (values 1..G) #' @keywords internal -build_cluster_index <- function(dt, unit, cluster, all_units) { +build_cluster_index <- function(dt, idname, clustervars, all_units) { # Extract time-invariant cluster id per unit using base R tapply - cl_vals <- dt[[cluster]] - unit_id_vals <- dt[[unit]] + cl_vals <- dt[[clustervars]] + unit_id_vals <- dt[[idname]] cl_map <- tapply(cl_vals, unit_id_vals, function(x) x[1L]) cl_ids <- cl_map[match(all_units, names(cl_map))] diff --git a/R/edid-methods.R b/R/edid-methods.R index c3b42c0..ad43739 100644 --- a/R/edid-methods.R +++ b/R/edid-methods.R @@ -3,7 +3,8 @@ #' Print method for edid_fit objects #' -#' Calls \code{summary.edid_fit()} and returns the object invisibly. +#' Displays the ATT(g,t) table in the same style as \code{print.MP} / +#' \code{summary.MP}, followed by footer metadata. #' #' @param x an \code{edid_fit} object #' @param ... additional arguments (currently ignored) @@ -11,14 +12,75 @@ #' @return \code{x} invisibly #' @export print.edid_fit <- function(x, ...) { - summary(x, ...) + cat("\n") + cat("Call:\n") + print(x$call) + cat("\n") + + cat("Group-Time Average Treatment Effects:\n") + + alp <- x$alpha + # CI label: pointwise for analytical; simult if bootstrap + cband_text1a <- paste0(100 * (1 - alp), "% ") + cband_text1b <- ifelse(isTRUE(x$bstrap), "Simult. ", "Pointwise ") + cband_text1 <- paste0("[", cband_text1a, cband_text1b) + + att_df <- x$att_gt + if (!is.null(att_df) && nrow(att_df) > 0L) { + ci_lower <- att_df$ci_lower + ci_upper <- att_df$ci_upper + + sig <- (ci_upper < 0) | (ci_lower > 0) + sig[is.na(sig)] <- FALSE + sig_text <- ifelse(sig, "*", "") + + out <- cbind.data.frame( + att_df$group, + att_df$time, + att_df$att, + att_df$se, + ci_lower, + ci_upper + ) + out <- round(out, 4) + out <- cbind.data.frame(out, sig_text) + colnames(out) <- c("Group", "Time", "ATT(g,t)", "Std. Error", + cband_text1, "Conf. Band]", "") + print(out, row.names = FALSE) + } else { + cat(" (no cells)\n") + } + + cat("---\n") + cat("Signif. codes: `*' confidence band does not cover 0") + cat("\n\n") + + # Control group footer + cg <- x$control_group + cg_text <- if (cg == "nevertreated") "Never Treated" else + if (cg == "last_cohort") "Last Cohort" else cg + cat("Control Group: ") + cat(cg_text) + cat(", ") + cat("Anticipation Periods: ") + cat(x$anticipation) + cat("\n") + + cat("Estimation Method: Efficient DiD (Chen, Sant'Anna & Xie 2025)\n") + + pt_text <- if (x$pt_assumption == "all") "PT-All" else "PT-Post" + cat("PT Assumption: ") + cat(pt_text) + cat("\n") + invisible(x) } #' Summary method for edid_fit objects #' #' Prints a structured summary of the EDiD estimation results including -#' metadata, the cell-level ATT table, and aggregated estimates. +#' the ATT(g,t) table (in MP style) plus aggregated overall, event-study, +#' and group estimates. #' #' @param object an \code{edid_fit} object #' @param ... additional arguments (currently ignored) @@ -26,44 +88,8 @@ print.edid_fit <- function(x, ...) { #' @return \code{object} invisibly #' @export summary.edid_fit <- function(object, ...) { - cat("\n=== Efficient Difference-in-Differences (EDiD) ===\n\n") - - # Metadata - cat(sprintf("PT assumption : %s\n", object$pt_assumption)) - cat(sprintf("Control group : %s\n", object$control_group)) - cat(sprintf("Anticipation : %d\n", object$anticipation)) - cat(sprintf("Units (n) : %d\n", object$n)) - cat(sprintf("Time periods (T) : %d\n", object$T_periods)) - cat(sprintf("Treatment cohorts : %s\n", - paste(object$treatment_groups, collapse = ", "))) - cat(sprintf("Inference type : %s\n", object$inference_type)) - if (!is.null(object$cluster)) { - cat(sprintf("Cluster variable : %s\n", object$cluster)) - } - cat(sprintf("Significance (alpha): %.3f\n\n", object$alpha)) - - # Cell-level ATT table (compact) - cat("--- Cell-level ATT(g, t) ---\n") - if (!is.null(object$att_gt) && nrow(object$att_gt) > 0L) { - att_print <- object$att_gt - att_print$pre <- ifelse(att_print$is_pre, "pre", "post") - # Round numeric columns for display - fmt_num <- function(x) ifelse(is.na(x), "NA", sprintf("%.4f", x)) - out <- data.frame( - group = att_print$group, - time = att_print$time, - type = att_print$pre, - att = fmt_num(att_print$att), - se = fmt_num(att_print$se), - ci_lower = fmt_num(att_print$ci_lower), - ci_upper = fmt_num(att_print$ci_upper), - p_value = fmt_num(att_print$p_value), - stringsAsFactors = FALSE - ) - print(out, row.names = FALSE, quote = FALSE) - } else { - cat(" (no cells)\n") - } + # First, print the ATT(g,t) table in MP format + print.edid_fit(object, ...) # Overall ATT if (!is.null(object$overall)) { diff --git a/R/edid-validate.R b/R/edid-validate.R index bb2709d..9e6a032 100644 --- a/R/edid-validate.R +++ b/R/edid-validate.R @@ -8,25 +8,25 @@ #' on any failure. #' #' @param data data.frame or coercible -#' @param outcome character scalar: outcome column name -#' @param unit character scalar: unit id column name -#' @param time character scalar: time column name -#' @param first_treat character scalar: first-treatment-period column name +#' @param yname character scalar: outcome column name +#' @param idname character scalar: unit id column name +#' @param tname character scalar: time column name +#' @param gname character scalar: first-treatment-period column name #' @param covariates character vector or NULL #' @param pt_assumption character scalar, already matched via \code{match.arg} -#' @param alpha numeric scalar in (0, 1) -#' @param cluster character scalar or NULL +#' @param alp numeric scalar in (0, 1) +#' @param clustervars character scalar or NULL #' @param control_group character scalar, already matched via \code{match.arg} -#' @param n_bootstrap non-negative integer +#' @param biters non-negative integer (internal bootstrap iterations) #' @param anticipation non-negative integer #' @param survey_design always NULL (survey not yet implemented) #' #' @return invisibly TRUE #' @keywords internal validate_edid_inputs <- function( - data, outcome, unit, time, first_treat, covariates, - pt_assumption, alpha, cluster, control_group, - n_bootstrap, anticipation, survey_design + data, yname, idname, tname, gname, covariates, + pt_assumption, alp, clustervars, control_group, + biters, anticipation, survey_design ) { # ------------------------------------------------------------------ @@ -45,7 +45,7 @@ validate_edid_inputs <- function( } # ------------------------------------------------------------------ - # 2. outcome / unit / time / first_treat are character scalars naming + # 2. yname / idname / tname / gname are character scalars naming # existing columns # ------------------------------------------------------------------ .check_col <- function(arg, argname) { @@ -56,73 +56,70 @@ validate_edid_inputs <- function( stop(sprintf("`%s` = \"%s\" is not a column in `data`.", argname, arg)) } } - .check_col(outcome, "outcome") - .check_col(unit, "unit") - .check_col(time, "time") - .check_col(first_treat, "first_treat") + .check_col(yname, "yname") + .check_col(idname, "idname") + .check_col(tname, "tname") + .check_col(gname, "gname") # Columns must be distinct - col_names <- c(outcome, unit, time, first_treat) + col_names <- c(yname, idname, tname, gname) if (anyDuplicated(col_names)) { - stop("`outcome`, `unit`, `time`, and `first_treat` must name distinct columns.") + stop("`yname`, `idname`, `tname`, and `gname` must name distinct columns.") } # ------------------------------------------------------------------ - # 3. outcome column is numeric; no NA; all finite + # 3. yname column is numeric; no NA; all finite # ------------------------------------------------------------------ - y_col <- data[[outcome]] + y_col <- data[[yname]] if (!is.numeric(y_col)) { - stop(sprintf("Column `%s` (outcome) must be numeric.", outcome)) + stop(sprintf("Column `%s` (yname) must be numeric.", yname)) } if (anyNA(y_col)) { - stop(sprintf("Column `%s` (outcome) contains NA values. ", - outcome), + stop(sprintf("Column `%s` (yname) contains NA values. ", yname), "edid() requires a complete, balanced panel with no missing outcomes.") } if (!all(is.finite(y_col))) { - stop(sprintf("Column `%s` (outcome) contains non-finite values (Inf/-Inf/NaN). ", - outcome), + stop(sprintf("Column `%s` (yname) contains non-finite values (Inf/-Inf/NaN). ", yname), "edid() requires all outcomes to be finite.") } # ------------------------------------------------------------------ - # 4. time column is numeric; no NA + # 4. tname column is numeric; no NA # ------------------------------------------------------------------ - t_col <- data[[time]] + t_col <- data[[tname]] if (!is.numeric(t_col)) { - stop(sprintf("Column `%s` (time) must be numeric.", time)) + stop(sprintf("Column `%s` (tname) must be numeric.", tname)) } if (anyNA(t_col)) { - stop(sprintf("Column `%s` (time) contains NA values.", time)) + stop(sprintf("Column `%s` (tname) contains NA values.", tname)) } # ------------------------------------------------------------------ - # 5. first_treat column is numeric; no NA + # 5. gname column is numeric; no NA # ------------------------------------------------------------------ - ft_col <- data[[first_treat]] + ft_col <- data[[gname]] if (!is.numeric(ft_col)) { - stop(sprintf("Column `%s` (first_treat) must be numeric.", first_treat)) + stop(sprintf("Column `%s` (gname) must be numeric.", gname)) } if (anyNA(ft_col)) { - stop(sprintf("Column `%s` (first_treat) contains NA values. ", - first_treat), + stop(sprintf("Column `%s` (gname) contains NA values. ", gname), "Use Inf to denote never-treated units.") } # ------------------------------------------------------------------ - # 6. No duplicate (unit, time) rows + # 6. No duplicate (idname, tname) rows # ------------------------------------------------------------------ - ut_key <- paste(data[[unit]], data[[time]], sep = "___") + ut_key <- paste(data[[idname]], data[[tname]], sep = "___") if (anyDuplicated(ut_key)) { - stop("Duplicate (unit, time) pairs found in `data`. ", + stop("Duplicate (idname, tname) pairs found in `data`. ", "edid() requires a balanced panel with exactly one observation per unit-period.") } # ------------------------------------------------------------------ # 7. Panel is balanced: every unit appears in every time period # ------------------------------------------------------------------ - all_units_v <- unique(data[[unit]]) - all_times_v <- unique(data[[time]]) + all_units_v <- unique(data[[idname]]) + all_times_v <- unique(data[[tname]]) n_units <- length(all_units_v) n_times <- length(all_times_v) expected_obs <- n_units * n_times @@ -134,28 +131,28 @@ validate_edid_inputs <- function( } # ------------------------------------------------------------------ - # 8. Treatment is absorbing: first_treat is constant within unit + # 8. Treatment is absorbing: gname is constant within unit # ------------------------------------------------------------------ - ft_by_unit <- tapply(data[[first_treat]], data[[unit]], function(x) length(unique(x))) + ft_by_unit <- tapply(data[[gname]], data[[idname]], function(x) length(unique(x))) if (any(ft_by_unit > 1L)) { bad <- names(ft_by_unit)[ft_by_unit > 1L] stop(sprintf( - "`%s` (first_treat) is not constant within unit for %d unit(s) (e.g., %s). ", - first_treat, length(bad), bad[1]), + "`%s` (gname) is not constant within unit for %d unit(s) (e.g., %s). ", + gname, length(bad), bad[1]), "Treatment must be absorbing.") } # ------------------------------------------------------------------ # 9-10. Control group availability # ------------------------------------------------------------------ - # Get time-invariant first_treat per unit (one row per unit) - unit_ft <- tapply(data[[first_treat]], data[[unit]], `[`, 1L) + # Get time-invariant gname per unit (one row per unit) + unit_ft <- tapply(data[[gname]], data[[idname]], `[`, 1L) - if (control_group == "never_treated") { + if (control_group == "nevertreated") { n_never <- sum(is.infinite(unit_ft)) if (n_never == 0L) { - stop("No never-treated units found (`first_treat == Inf`). ", - "edid() requires never-treated units when `control_group = \"never_treated\"`.") + stop("No never-treated units found (`gname == Inf`). ", + "edid() requires never-treated units when `control_group = \"nevertreated\"`.") } } else { # last_cohort @@ -188,18 +185,18 @@ validate_edid_inputs <- function( } # ------------------------------------------------------------------ - # 13. alpha in (0, 1) + # 13. alp in (0, 1) # ------------------------------------------------------------------ - if (!is.numeric(alpha) || length(alpha) != 1L || alpha <= 0 || alpha >= 1) { - stop("`alpha` must be a numeric scalar strictly between 0 and 1.") + if (!is.numeric(alp) || length(alp) != 1L || alp <= 0 || alp >= 1) { + stop("`alp` must be a numeric scalar strictly between 0 and 1.") } # ------------------------------------------------------------------ - # 14. n_bootstrap >= 0 integer + # 14. biters >= 0 integer # ------------------------------------------------------------------ - if (!is.numeric(n_bootstrap) || length(n_bootstrap) != 1L || - n_bootstrap < 0 || n_bootstrap != floor(n_bootstrap)) { - stop("`n_bootstrap` must be a non-negative integer.") + if (!is.numeric(biters) || length(biters) != 1L || + biters < 0 || biters != floor(biters)) { + stop("`biters` must be a non-negative integer.") } # ------------------------------------------------------------------ @@ -220,26 +217,26 @@ validate_edid_inputs <- function( } # ------------------------------------------------------------------ - # 16. cluster column checks + # 16. clustervars column checks # ------------------------------------------------------------------ - if (!is.null(cluster)) { - if (!is.character(cluster) || length(cluster) != 1L) { - stop("`cluster` must be a character scalar naming a column in `data`, or NULL.") + if (!is.null(clustervars)) { + if (!is.character(clustervars) || length(clustervars) != 1L) { + stop("`clustervars` must be a character scalar naming a column in `data`, or NULL.") } - if (!cluster %in% names(data)) { - stop(sprintf("`cluster` = \"%s\" is not a column in `data`.", cluster)) + if (!clustervars %in% names(data)) { + stop(sprintf("`clustervars` = \"%s\" is not a column in `data`.", clustervars)) } - cl_col <- data[[cluster]] + cl_col <- data[[clustervars]] if (anyNA(cl_col)) { - stop(sprintf("Cluster column `%s` contains NA values.", cluster)) + stop(sprintf("Cluster column `%s` contains NA values.", clustervars)) } # Time-invariant within unit - cl_by_unit <- tapply(cl_col, data[[unit]], function(x) length(unique(x))) + cl_by_unit <- tapply(cl_col, data[[idname]], function(x) length(unique(x))) if (any(cl_by_unit > 1L)) { bad <- names(cl_by_unit)[cl_by_unit > 1L] stop(sprintf( "Cluster variable `%s` is not time-invariant for %d unit(s) (e.g., %s). ", - cluster, length(bad), bad[1]), + clustervars, length(bad), bad[1]), "Cluster variable must be constant within unit.") } } diff --git a/R/edid.R b/R/edid.R index 5ab9959..ae6b4a9 100644 --- a/R/edid.R +++ b/R/edid.R @@ -8,13 +8,14 @@ #' #' @param data A \code{data.frame}, \code{data.table}, or tibble in long format #' (one row per unit-time observation). -#' @param outcome Character scalar: name of the outcome column (must be numeric +#' @param yname Character scalar: name of the outcome column (must be numeric #' with no missing or non-finite values). -#' @param unit Character scalar: name of the unit identifier column. -#' @param time Character scalar: name of the time period column (numeric). -#' @param first_treat Character scalar: name of the column recording each unit's -#' first treatment period. Never-treated units should have \code{Inf} (or -#' \code{NA} is not accepted --- use \code{Inf} explicitly). +#' @param idname Character scalar: name of the unit identifier column. +#' @param tname Character scalar: name of the time period column (numeric). +#' @param gname Character scalar: name of the column recording each unit's +#' first treatment period. Never-treated units should have \code{Inf} or +#' \code{0} (the \code{att_gt()} convention). \code{0} is automatically +#' converted to \code{Inf} internally. #' @param covariates Character vector of covariate column names, or \code{NULL} #' (default). \strong{Currently not implemented}: passing non-NULL triggers an #' error. @@ -25,18 +26,22 @@ #' \item{\code{"post"}}{PT-Post: parallel trends holds only for the period #' immediately before treatment. Each cell uses a single DiD moment.} #' } -#' @param alpha Significance level for confidence intervals. Default \code{0.05}. -#' @param cluster Character scalar naming a time-invariant cluster variable in -#' \code{data}, or \code{NULL} for no clustering (default). When supplied, +#' @param alp Significance level for confidence intervals. Default \code{0.05}. +#' @param clustervars Character scalar naming a time-invariant cluster variable +#' in \code{data}, or \code{NULL} for no clustering (default). When supplied, #' cluster-robust standard errors are computed via the sandwich EIF formula. +#' Note: edid() currently supports only a single cluster variable internally. #' @param control_group Control group definition. One of: #' \describe{ -#' \item{\code{"never_treated"}}{Use never-treated units (default).} +#' \item{\code{"nevertreated"}}{Use never-treated units (default).} #' \item{\code{"last_cohort"}}{Use the last-treated cohort as #' pseudo-controls (relabeled as never-treated internally).} #' } -#' @param n_bootstrap Non-negative integer: number of multiplier bootstrap draws. -#' \code{0} (default) returns analytical standard errors only. +#' @param bstrap Logical: whether to use multiplier bootstrap inference. +#' Default \code{FALSE} (analytical standard errors). When \code{TRUE}, +#' \code{biters} bootstrap draws are used. +#' @param biters Positive integer: number of multiplier bootstrap iterations. +#' Default \code{1000L}. Only used when \code{bstrap = TRUE}. #' @param bootstrap_weights Distribution for multiplier weights. One of #' \code{"rademacher"} (default), \code{"mammen"}, or \code{"webb"}. #' @param seed Integer seed for reproducibility of bootstrap draws, or @@ -54,7 +59,7 @@ #' implemented; passing a non-NULL value triggers an error. #' @param store_eif Logical: if \code{TRUE}, store the full \eqn{n \times K} #' EIF matrix in \code{edid_fit$eif}. Default \code{FALSE}. The EIF is -#' always computed internally when \code{n_bootstrap > 0}. +#' always computed internally when \code{bstrap = TRUE}. #' #' @return An object of class \code{edid_fit} (a list) with elements: #' \describe{ @@ -66,6 +71,7 @@ #' \item{\code{group}}{List of per-cohort ATTs.} #' \item{\code{eif}}{EIF matrix or \code{NULL}.} #' \item{\code{bootstrap}}{Bootstrap results or \code{NULL}.} +#' \item{\code{bstrap}}{Logical: whether bootstrap inference was used.} #' } #' #' @references Chen, L., Sant'Anna, P. H. C., & Xie, Y. (2025). @@ -97,11 +103,11 @@ #' ) #' # Fit EDiD (no-covariate, PT-All, analytical SE) #' fit <- edid( -#' data = panel_df, -#' outcome = "y", -#' unit = "id", -#' time = "period", -#' first_treat = "first_treat", +#' data = panel_df, +#' yname = "y", +#' idname = "id", +#' tname = "period", +#' gname = "first_treat", #' pt_assumption = "all" #' ) #' # View overall ATT @@ -112,16 +118,17 @@ #' @export edid <- function( data, - outcome, - unit, - time, - first_treat, + yname, + idname, + tname, + gname, covariates = NULL, pt_assumption = c("all", "post"), - alpha = 0.05, - cluster = NULL, - control_group = c("never_treated", "last_cohort"), - n_bootstrap = 0L, + alp = 0.05, + clustervars = NULL, + control_group = c("nevertreated", "last_cohort"), + bstrap = FALSE, + biters = 1000L, bootstrap_weights = c("rademacher", "mammen", "webb"), seed = NULL, anticipation = 0L, @@ -142,24 +149,37 @@ edid <- function( # When "all" is present it subsumes the others if ("all" %in% aggregate) aggregate <- "all" - n_bootstrap <- as.integer(n_bootstrap) anticipation <- as.integer(anticipation) + # ------------------------------------------------------------------ + # Bootstrap: derive internal n_bootstrap from bstrap + biters + # ------------------------------------------------------------------ + n_bootstrap_internal <- if (bstrap) as.integer(biters) else 0L + + # ------------------------------------------------------------------ + # Accept G=0 (att_gt convention) or G=Inf (edid native) for never-treated + # Convert 0 -> Inf internally, matching att_gt's internal transformation + data <- as.data.frame(data) + zero_nt <- is.finite(data[[gname]]) & data[[gname]] == 0 + if (any(zero_nt)) { + data[[gname]] <- ifelse(zero_nt, Inf, data[[gname]]) + } + # ------------------------------------------------------------------ # Validation # ------------------------------------------------------------------ validate_edid_inputs( data = data, - outcome = outcome, - unit = unit, - time = time, - first_treat = first_treat, + yname = yname, + idname = idname, + tname = tname, + gname = gname, covariates = covariates, pt_assumption = pt_assumption, - alpha = alpha, - cluster = cluster, + alp = alp, + clustervars = clustervars, control_group = control_group, - n_bootstrap = n_bootstrap, + biters = n_bootstrap_internal, anticipation = anticipation, survey_design = survey_design ) @@ -169,12 +189,12 @@ edid <- function( # ------------------------------------------------------------------ panel_obj <- prepare_edid_panel( data = data, - outcome = outcome, - unit = unit, - time = time, - first_treat = first_treat, + yname = yname, + idname = idname, + tname = tname, + gname = gname, covariates = covariates, - cluster = cluster, + clustervars = clustervars, control_group = control_group, anticipation = anticipation ) @@ -184,14 +204,14 @@ edid <- function( # EIF is always needed for aggregated SE computation, not just bootstrap. # ------------------------------------------------------------------ do_any_agg <- !("none" %in% aggregate) - need_eif_for_boot <- (n_bootstrap > 0L) + need_eif_for_boot <- (n_bootstrap_internal > 0L) # need_eif: TRUE whenever we need aggregated inference OR bootstrap need_eif_internal <- do_any_agg || need_eif_for_boot fit_result <- fit_edid_cells( panel_obj = panel_obj, pt_assumption = pt_assumption, - alpha = alpha, + alpha = alp, store_eif = store_eif, covariates = covariates, need_eif = need_eif_internal @@ -230,22 +250,22 @@ edid <- function( group_res <- NULL if (do_overall) { - overall_res <- aggregate_overall_edid(cells, eif_matrix, cell_index, panel_obj, alpha) + overall_res <- aggregate_overall_edid(cells, eif_matrix, cell_index, panel_obj, alp) } if (do_event_study) { event_study_res <- aggregate_event_study_edid( - cells, eif_matrix, cell_index, panel_obj, alpha, balance_e + cells, eif_matrix, cell_index, panel_obj, alp, balance_e ) } if (do_group) { - group_res <- aggregate_group_edid(cells, eif_matrix, cell_index, panel_obj, alpha) + group_res <- aggregate_group_edid(cells, eif_matrix, cell_index, panel_obj, alp) } # ------------------------------------------------------------------ # Bootstrap # ------------------------------------------------------------------ bootstrap_res <- NULL - if (n_bootstrap > 0L) { + if (n_bootstrap_internal > 0L) { if (is.null(eif_matrix)) { warning("EIF matrix is NULL; bootstrap cannot be run. ", "This should not happen --- please report this issue.") @@ -257,18 +277,18 @@ edid <- function( eif_matrix = eif_matrix, cell_index = cell_index, panel_obj = panel_obj, - n_bootstrap = n_bootstrap, + n_bootstrap = n_bootstrap_internal, bootstrap_weights = bootstrap_weights, seed = seed, aggregate = "all", balance_e = balance_e, - alpha = alpha + alpha = alp ) class(bootstrap_res) <- c("edid_bootstrap", "list") # Overwrite SEs/CIs with bootstrap versions if (do_overall && !is.null(overall_res) && !is.null(bootstrap_res$overall_b)) { - bs_ov <- compute_bootstrap_stats_edid(bootstrap_res$overall_b, overall_res$att, alpha) + bs_ov <- compute_bootstrap_stats_edid(bootstrap_res$overall_b, overall_res$att, alp) overall_res$se <- bs_ov$se_boot overall_res$ci_lower <- bs_ov$ci_lower overall_res$ci_upper <- bs_ov$ci_upper @@ -283,7 +303,7 @@ edid <- function( for (e_nm in names(event_study_res)) { draws <- bootstrap_res$event_study_b[[e_nm]] if (is.null(draws)) next - bs_es <- compute_bootstrap_stats_edid(draws, event_study_res[[e_nm]]$att, alpha) + bs_es <- compute_bootstrap_stats_edid(draws, event_study_res[[e_nm]]$att, alp) event_study_res[[e_nm]]$se <- bs_es$se_boot event_study_res[[e_nm]]$ci_lower <- bs_es$ci_lower event_study_res[[e_nm]]$ci_upper <- bs_es$ci_upper @@ -295,7 +315,7 @@ edid <- function( for (g_nm in names(group_res)) { draws <- bootstrap_res$group_b[[g_nm]] if (is.null(draws)) next - bs_gr <- compute_bootstrap_stats_edid(draws, group_res[[g_nm]]$att, alpha) + bs_gr <- compute_bootstrap_stats_edid(draws, group_res[[g_nm]]$att, alp) group_res[[g_nm]]$se <- bs_gr$se_boot group_res[[g_nm]]$ci_lower <- bs_gr$ci_lower group_res[[g_nm]]$ci_upper <- bs_gr$ci_upper @@ -319,13 +339,14 @@ edid <- function( call = mc, pt_assumption = pt_assumption, control_group = control_group, - alpha = alpha, + alpha = alp, n = panel_obj$n, T_periods = panel_obj$T_periods, treatment_groups = panel_obj$treatment_groups, anticipation = panel_obj$anticipation, - inference_type = if (n_bootstrap > 0L) "bootstrap" else "analytical", - cluster = cluster, + inference_type = if (n_bootstrap_internal > 0L) "bootstrap" else "analytical", + clustervars = clustervars, + bstrap = bstrap, cells = cells, att_gt = att_gt_df, overall = overall_res, @@ -333,7 +354,7 @@ edid <- function( group = group_res, eif = eif_export, bootstrap = bootstrap_res, - n_bootstrap = n_bootstrap, + n_bootstrap = n_bootstrap_internal, bootstrap_weights = bootstrap_weights ) diff --git a/compare_att_gt_edid.R b/compare_att_gt_edid.R new file mode 100644 index 0000000..87fded5 --- /dev/null +++ b/compare_att_gt_edid.R @@ -0,0 +1,216 @@ +############################################################################### +# compare_att_gt_edid.R +# +# Simulate a staggered adoption panel and compare estimates from: +# (1) att_gt() -- Callaway & Sant'Anna (2021) +# (2) edid() -- Chen, Sant'Anna & Xie (2025), efficient DiD +# +# True ATT = 1 in all post-treatment periods (homogeneous, no dynamics). +############################################################################### + +devtools::load_all(quiet = TRUE) # loads att_gt(), edid(), and all helpers + +set.seed(2025) + +# ── 1. Simulate balanced staggered panel ────────────────────────────────────── +sp <- reset.sim(time.periods = 6, n = 2000) +df <- build_sim_dataset(sp_list = sp, panel = TRUE) + +# build_sim_dataset returns G = 0 for never-treated (att_gt convention). +# edid() now accepts G=0 directly and converts 0 -> Inf internally, +# so we no longer need a separate G_edid column. + +cat("─── Dataset summary ────────────────────────────────────────────────────\n") +cat("Periods:", sort(unique(df$period)), "\n") +cat("Cohorts (att_gt coding, 0 = never):", sort(unique(df$G)), "\n") +cat("Units:", length(unique(df$id)), " | Obs:", nrow(df), "\n\n") + + +# ── 2. Fit att_gt() (Callaway-Sant'Anna, no covariates) ─────────────────────── +cs <- att_gt( + yname = "Y", + tname = "period", + idname = "id", + gname = "G", + data = df, + control_group = "nevertreated", + est_method = "reg", # outcome-regression, closest to no-cov DiD + bstrap = FALSE, + cband = FALSE, + print_details = FALSE +) + +cs_overall <- aggte(cs, type = "simple") +cs_eventstudy <- aggte(cs, type = "dynamic") +cs_group <- aggte(cs, type = "group") + + +# ── 3. Fit edid() (Chen-Sant'Anna-Xie, no covariates, PT-All) ───────────────── +# Note: gname = "G" directly -- edid() auto-converts G=0 to Inf internally. +ed <- edid( + data = df, + yname = "Y", + idname = "id", + tname = "period", + gname = "G", + pt_assumption = "post", + control_group = "nevertreated", + alp = 0.05 +) + + +# ── 4. Compare cell-level ATT(g, t) ────────────────────────────────────────── +cat("─── Cell-level ATT(g,t) comparison ─────────────────────────────────────\n") + +# CS cell-level estimates +cs_gt <- data.frame( + group = cs$group, + time = cs$t, + att_cs = round(cs$att, 4), + se_cs = round(cs$se, 4), + is_pre = cs$t < cs$group +) + +# EDiD cell-level estimates (post-treatment only, drop skipped cells) +ed_gt <- ed$att_gt[!is.na(ed$att_gt$att), c("group", "time", "att", "se", "is_pre")] +names(ed_gt)[3:4] <- c("att_ed", "se_ed") +ed_gt$att_ed <- round(ed_gt$att_ed, 4) +ed_gt$se_ed <- round(ed_gt$se_ed, 4) + +# Merge on (group, time) +cmp_gt <- merge(cs_gt, ed_gt, by = c("group", "time", "is_pre"), all = TRUE) +cmp_gt <- cmp_gt[order(cmp_gt$is_pre, cmp_gt$group, cmp_gt$time), ] + +# Highlight post-treatment cells +post_gt <- subset(cmp_gt, !is_pre) +pre_gt <- subset(cmp_gt, is_pre) + +cat("\nPost-treatment cells (ATT should \u2248 1):\n") +print(post_gt, row.names = FALSE) + +cat("\nPre-treatment placebo cells (ATT should \u2248 0):\n") +print(pre_gt, row.names = FALSE) + +cat("\nMean ATT diff (post): CS - EDiD =", + round(mean(post_gt$att_cs - post_gt$att_ed, na.rm = TRUE), 4), "\n") + + +# ── 5. Compare overall ATT ──────────────────────────────────────────────────── +cat("\n─── Overall ATT ─────────────────────────────────────────────────────────\n") +cat(sprintf(" %-20s ATT = %6.4f SE = %6.4f 95%% CI = [%6.4f, %6.4f]\n", + "att_gt (CS-simple):", + cs_overall$overall.att, + cs_overall$overall.se, + cs_overall$overall.att - qnorm(0.975) * cs_overall$overall.se, + cs_overall$overall.att + qnorm(0.975) * cs_overall$overall.se)) +cat(sprintf(" %-20s ATT = %6.4f SE = %6.4f 95%% CI = [%6.4f, %6.4f]\n", + "edid (PT-Post):", + ed$overall$att, + ed$overall$se, + ed$overall$ci_lower, + ed$overall$ci_upper)) +cat(" True ATT = 1\n") + + +# ── 6. Compare event-study ──────────────────────────────────────────────────── +cat("\n─── Event-study (relative-time ATTs) ───────────────────────────────────\n") + +# CS event-study +cs_es <- data.frame( + rel_time = cs_eventstudy$egt, + att_cs = round(cs_eventstudy$att.egt, 4), + se_cs = round(cs_eventstudy$se.egt, 4) +) + +# EDiD event-study +ed_es_names <- names(ed$event_study) +ed_es <- data.frame( + rel_time = as.numeric(sub("^e", "", ed_es_names)), + att_ed = round(vapply(ed$event_study, `[[`, numeric(1), "att"), 4), + se_ed = round(vapply(ed$event_study, `[[`, numeric(1), "se"), 4) +) + +cmp_es <- merge(cs_es, ed_es, by = "rel_time", all = TRUE) +cmp_es <- cmp_es[order(cmp_es$rel_time), ] +print(cmp_es, row.names = FALSE) + + +# ── 7. Compare group-level ATTs ─────────────────────────────────────────────── +cat("\n─── Group-level ATTs ────────────────────────────────────────────────────\n") + +cs_grp <- data.frame( + group = cs_group$egt, + att_cs = round(cs_group$att.egt, 4), + se_cs = round(cs_group$se.egt, 4) +) + +ed_grp_names <- names(ed$group) +ed_grp <- data.frame( + group = as.numeric(sub("^g", "", ed_grp_names)), + att_ed = round(vapply(ed$group, `[[`, numeric(1), "att"), 4), + se_ed = round(vapply(ed$group, `[[`, numeric(1), "se"), 4) +) + +cmp_grp <- merge(cs_grp, ed_grp, by = "group", all = TRUE) +cmp_grp <- cmp_grp[order(cmp_grp$group), ] +print(cmp_grp, row.names = FALSE) + + +# ── 8. SE comparison: who is more efficient? ───────────────────────────────── +cat("\n─── Efficiency comparison (post-treatment cells only) ──────────────────\n") +post_with_both <- subset(post_gt, !is.na(att_cs) & !is.na(att_ed)) +post_with_both$se_ratio <- round(post_with_both$se_cs / post_with_both$se_ed, 3) +cat("SE ratio = se(CS) / se(EDiD). Ratio > 1 means EDiD is more efficient.\n") +print(post_with_both[, c("group", "time", "se_cs", "se_ed", "se_ratio")], + row.names = FALSE) +cat(sprintf("\nMedian SE ratio (CS / EDiD): %.3f\n", + median(post_with_both$se_ratio, na.rm = TRUE))) + + +# ── 9. Quick plot: event-study side by side ─────────────────────────────────── +if (requireNamespace("ggplot2", quietly = TRUE)) { + library(ggplot2) + + es_plot <- rbind( + transform(cmp_es[!is.na(cmp_es$att_cs), ], + att = att_cs, + se = se_cs, + Estimator = "att_gt (CS)")[, c("rel_time", "att", "se", "Estimator")], + transform(cmp_es[!is.na(cmp_es$att_ed), ], + att = att_ed, + se = se_ed, + Estimator = "edid (CSX)" )[, c("rel_time", "att", "se", "Estimator")] + ) + es_plot$ci_lo <- es_plot$att - qnorm(0.975) * es_plot$se + es_plot$ci_hi <- es_plot$att + qnorm(0.975) * es_plot$se + + # Dodge slightly so CIs don't overlap + es_plot$rel_time_jit <- ifelse(es_plot$Estimator == "att_gt (CS)", + es_plot$rel_time - 0.1, + es_plot$rel_time + 0.1) + + p <- ggplot(es_plot, aes(x = rel_time_jit, y = att, + color = Estimator, fill = Estimator)) + + geom_hline(yintercept = 0, linetype = "dashed", color = "grey60") + + geom_hline(yintercept = 1, linetype = "dotted", color = "black", alpha = 0.5) + + geom_ribbon(aes(ymin = ci_lo, ymax = ci_hi), alpha = 0.15, color = NA) + + geom_line(aes(x = rel_time_jit)) + + geom_point(size = 2) + + geom_errorbar(aes(ymin = ci_lo, ymax = ci_hi), width = 0.15) + + scale_x_continuous(breaks = sort(unique(es_plot$rel_time)), + labels = sort(unique(es_plot$rel_time))) + + labs( + title = "Event-study: att_gt (CS) vs edid (CSX)", + subtitle = "Dotted line = true ATT = 1", + x = "Relative time (periods since first treatment)", + y = "ATT estimate", + color = NULL, fill = NULL + ) + + theme_bw(base_size = 13) + + theme(legend.position = "bottom") + + print(p) + cat("\nEvent-study plot printed.\n") +} + +cat("\n─── Done ────────────────────────────────────────────────────────────────\n") diff --git a/man/aggte_edid.Rd b/man/aggte_edid.Rd new file mode 100644 index 0000000..d2fbc69 --- /dev/null +++ b/man/aggte_edid.Rd @@ -0,0 +1,56 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggte.R +\name{aggte_edid} +\alias{aggte_edid} +\title{Aggregate edid_fit estimates} +\usage{ +aggte_edid( + edid_fit_obj, + type = c("simple", "dynamic", "group", "calendar"), + balance_e = NULL, + min_e = -Inf, + max_e = Inf, + na.rm = FALSE +) +} +\arguments{ +\item{edid_fit_obj}{An \code{edid_fit} object returned by \code{edid()}.} + +\item{type}{Character scalar: aggregation type. One of +\code{"simple"} (overall ATT), \code{"dynamic"} (event-study), +\code{"group"} (cohort-level ATT), or \code{"calendar"} (not implemented).} + +\item{balance_e}{Integer or \code{NULL}: if not \code{NULL}, restricts the +dynamic aggregation to relative times in +\eqn{[-\text{balance\_e}, \text{balance\_e}]}.} + +\item{min_e}{Numeric: minimum relative time to include in dynamic output. +Default \code{-Inf}.} + +\item{max_e}{Numeric: maximum relative time to include in dynamic output. +Default \code{Inf}.} + +\item{na.rm}{Logical: whether to remove NA ATT entries before aggregating. +Default \code{FALSE}.} +} +\value{ +An S3 object of class \code{c("AGGTEobj_edid", "list")} with fields +matching \code{AGGTEobj} where possible: +\describe{ +\item{\code{att.egt}}{Vector of ATT estimates for each index.} +\item{\code{se.egt}}{Vector of standard errors.} +\item{\code{egt}}{Vector of indices (relative time, group, etc.).} +\item{\code{type}}{The aggregation type string.} +\item{\code{overall.att}}{Scalar overall ATT.} +\item{\code{overall.se}}{Scalar overall SE.} +\item{\code{alp}}{Significance level used.} +\item{\code{call}}{The matched call.} +} +} +\description{ +Provides the same user-facing interface as \code{\link[did]{aggte}} but +accepts an \code{edid_fit} object produced by \code{\link{edid}}. +} +\seealso{ +\code{\link{edid}}, \code{\link[did]{aggte}} +} diff --git a/man/build_cluster_index.Rd b/man/build_cluster_index.Rd index 5ee77bb..df46369 100644 --- a/man/build_cluster_index.Rd +++ b/man/build_cluster_index.Rd @@ -4,14 +4,14 @@ \alias{build_cluster_index} \title{Build cluster integer index from cluster id column} \usage{ -build_cluster_index(dt, unit, cluster, all_units) +build_cluster_index(dt, idname, clustervars, all_units) } \arguments{ \item{dt}{data.table (long format), sorted by unit then time} -\item{unit}{character scalar: unit id column name} +\item{idname}{character scalar: unit id column name} -\item{cluster}{character scalar: cluster id column name} +\item{clustervars}{character scalar: cluster id column name} \item{all_units}{sorted vector of unique unit ids} } diff --git a/man/edid.Rd b/man/edid.Rd index 7b9a3ff..86dd71e 100644 --- a/man/edid.Rd +++ b/man/edid.Rd @@ -6,16 +6,17 @@ \usage{ edid( data, - outcome, - unit, - time, - first_treat, + yname, + idname, + tname, + gname, covariates = NULL, pt_assumption = c("all", "post"), - alpha = 0.05, - cluster = NULL, - control_group = c("never_treated", "last_cohort"), - n_bootstrap = 0L, + alp = 0.05, + clustervars = NULL, + control_group = c("nevertreated", "last_cohort"), + bstrap = FALSE, + biters = 1000L, bootstrap_weights = c("rademacher", "mammen", "webb"), seed = NULL, anticipation = 0L, @@ -29,16 +30,17 @@ edid( \item{data}{A \code{data.frame}, \code{data.table}, or tibble in long format (one row per unit-time observation).} -\item{outcome}{Character scalar: name of the outcome column (must be numeric +\item{yname}{Character scalar: name of the outcome column (must be numeric with no missing or non-finite values).} -\item{unit}{Character scalar: name of the unit identifier column.} +\item{idname}{Character scalar: name of the unit identifier column.} -\item{time}{Character scalar: name of the time period column (numeric).} +\item{tname}{Character scalar: name of the time period column (numeric).} -\item{first_treat}{Character scalar: name of the column recording each unit's -first treatment period. Never-treated units should have \code{Inf} (or -\code{NA} is not accepted --- use \code{Inf} explicitly).} +\item{gname}{Character scalar: name of the column recording each unit's +first treatment period. Never-treated units should have \code{Inf} or +\code{0} (the \code{att_gt()} convention). \code{0} is automatically +converted to \code{Inf} internally.} \item{covariates}{Character vector of covariate column names, or \code{NULL} (default). \strong{Currently not implemented}: passing non-NULL triggers an @@ -52,21 +54,26 @@ periods (default). Uses all valid \eqn{(g', t_{pre})} pairs.} immediately before treatment. Each cell uses a single DiD moment.} }} -\item{alpha}{Significance level for confidence intervals. Default \code{0.05}.} +\item{alp}{Significance level for confidence intervals. Default \code{0.05}.} -\item{cluster}{Character scalar naming a time-invariant cluster variable in -\code{data}, or \code{NULL} for no clustering (default). When supplied, -cluster-robust standard errors are computed via the sandwich EIF formula.} +\item{clustervars}{Character scalar naming a time-invariant cluster variable +in \code{data}, or \code{NULL} for no clustering (default). When supplied, +cluster-robust standard errors are computed via the sandwich EIF formula. +Note: edid() currently supports only a single cluster variable internally.} \item{control_group}{Control group definition. One of: \describe{ -\item{\code{"never_treated"}}{Use never-treated units (default).} +\item{\code{"nevertreated"}}{Use never-treated units (default).} \item{\code{"last_cohort"}}{Use the last-treated cohort as pseudo-controls (relabeled as never-treated internally).} }} -\item{n_bootstrap}{Non-negative integer: number of multiplier bootstrap draws. -\code{0} (default) returns analytical standard errors only.} +\item{bstrap}{Logical: whether to use multiplier bootstrap inference. +Default \code{FALSE} (analytical standard errors). When \code{TRUE}, +\code{biters} bootstrap draws are used.} + +\item{biters}{Positive integer: number of multiplier bootstrap iterations. +Default \code{1000L}. Only used when \code{bstrap = TRUE}.} \item{bootstrap_weights}{Distribution for multiplier weights. One of \code{"rademacher"} (default), \code{"mammen"}, or \code{"webb"}.} @@ -91,7 +98,7 @@ implemented; passing a non-NULL value triggers an error.} \item{store_eif}{Logical: if \code{TRUE}, store the full \eqn{n \times K} EIF matrix in \code{edid_fit$eif}. Default \code{FALSE}. The EIF is -always computed internally when \code{n_bootstrap > 0}.} +always computed internally when \code{bstrap = TRUE}.} } \value{ An object of class \code{edid_fit} (a list) with elements: @@ -104,6 +111,7 @@ att, se, ci_lower, ci_upper, t_stat, p_value, is_pre).} \item{\code{group}}{List of per-cohort ATTs.} \item{\code{eif}}{EIF matrix or \code{NULL}.} \item{\code{bootstrap}}{Bootstrap results or \code{NULL}.} +\item{\code{bstrap}}{Logical: whether bootstrap inference was used.} } } \description{ @@ -139,11 +147,11 @@ panel_df <- data.frame( ) # Fit EDiD (no-covariate, PT-All, analytical SE) fit <- edid( - data = panel_df, - outcome = "y", - unit = "id", - time = "period", - first_treat = "first_treat", + data = panel_df, + yname = "y", + idname = "id", + tname = "period", + gname = "first_treat", pt_assumption = "all" ) # View overall ATT diff --git a/man/prepare_edid_panel.Rd b/man/prepare_edid_panel.Rd index 10022b3..8360aea 100644 --- a/man/prepare_edid_panel.Rd +++ b/man/prepare_edid_panel.Rd @@ -6,32 +6,32 @@ \usage{ prepare_edid_panel( data, - outcome, - unit, - time, - first_treat, + yname, + idname, + tname, + gname, covariates = NULL, - cluster = NULL, - control_group = "never_treated", + clustervars = NULL, + control_group = "nevertreated", anticipation = 0L ) } \arguments{ \item{data}{data.frame (or data.table / tibble) already validated} -\item{outcome}{character scalar: outcome column name} +\item{yname}{character scalar: outcome column name} -\item{unit}{character scalar: unit id column name} +\item{idname}{character scalar: unit id column name} -\item{time}{character scalar: time column name} +\item{tname}{character scalar: time column name} -\item{first_treat}{character scalar: first-treatment-period column name} +\item{gname}{character scalar: first-treatment-period column name} \item{covariates}{NULL (stub)} -\item{cluster}{character scalar or NULL} +\item{clustervars}{character scalar or NULL} -\item{control_group}{\code{"never_treated"} or \code{"last_cohort"}} +\item{control_group}{\code{"nevertreated"} or \code{"last_cohort"}} \item{anticipation}{non-negative integer} } diff --git a/man/print.AGGTEobj_edid.Rd b/man/print.AGGTEobj_edid.Rd new file mode 100644 index 0000000..97384c5 --- /dev/null +++ b/man/print.AGGTEobj_edid.Rd @@ -0,0 +1,20 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggte.R +\name{print.AGGTEobj_edid} +\alias{print.AGGTEobj_edid} +\title{Print method for AGGTEobj_edid objects} +\usage{ +\method{print}{AGGTEobj_edid}(x, ...) +} +\arguments{ +\item{x}{an \code{AGGTEobj_edid} object} + +\item{...}{additional arguments (currently ignored)} +} +\value{ +\code{x} invisibly +} +\description{ +Prints aggregated treatment effects in a format similar to +\code{print.AGGTEobj}. +} diff --git a/man/print.edid_fit.Rd b/man/print.edid_fit.Rd index 329ba21..c91749c 100644 --- a/man/print.edid_fit.Rd +++ b/man/print.edid_fit.Rd @@ -15,5 +15,6 @@ \code{x} invisibly } \description{ -Calls \code{summary.edid_fit()} and returns the object invisibly. +Displays the ATT(g,t) table in the same style as \code{print.MP} / +\code{summary.MP}, followed by footer metadata. } diff --git a/man/summary.AGGTEobj_edid.Rd b/man/summary.AGGTEobj_edid.Rd new file mode 100644 index 0000000..43ff451 --- /dev/null +++ b/man/summary.AGGTEobj_edid.Rd @@ -0,0 +1,19 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/edid-aggte.R +\name{summary.AGGTEobj_edid} +\alias{summary.AGGTEobj_edid} +\title{Summary method for AGGTEobj_edid objects} +\usage{ +\method{summary}{AGGTEobj_edid}(object, ...) +} +\arguments{ +\item{object}{an \code{AGGTEobj_edid} object} + +\item{...}{additional arguments (currently ignored)} +} +\value{ +\code{object} invisibly +} +\description{ +Delegates to \code{print.AGGTEobj_edid}. +} diff --git a/man/summary.edid_fit.Rd b/man/summary.edid_fit.Rd index eca2595..d934456 100644 --- a/man/summary.edid_fit.Rd +++ b/man/summary.edid_fit.Rd @@ -16,5 +16,6 @@ } \description{ Prints a structured summary of the EDiD estimation results including -metadata, the cell-level ATT table, and aggregated estimates. +the ATT(g,t) table (in MP style) plus aggregated overall, event-study, +and group estimates. } diff --git a/man/validate_edid_inputs.Rd b/man/validate_edid_inputs.Rd index cd007d1..b71d15a 100644 --- a/man/validate_edid_inputs.Rd +++ b/man/validate_edid_inputs.Rd @@ -6,16 +6,16 @@ \usage{ validate_edid_inputs( data, - outcome, - unit, - time, - first_treat, + yname, + idname, + tname, + gname, covariates, pt_assumption, - alpha, - cluster, + alp, + clustervars, control_group, - n_bootstrap, + biters, anticipation, survey_design ) @@ -23,25 +23,25 @@ validate_edid_inputs( \arguments{ \item{data}{data.frame or coercible} -\item{outcome}{character scalar: outcome column name} +\item{yname}{character scalar: outcome column name} -\item{unit}{character scalar: unit id column name} +\item{idname}{character scalar: unit id column name} -\item{time}{character scalar: time column name} +\item{tname}{character scalar: time column name} -\item{first_treat}{character scalar: first-treatment-period column name} +\item{gname}{character scalar: first-treatment-period column name} \item{covariates}{character vector or NULL} \item{pt_assumption}{character scalar, already matched via \code{match.arg}} -\item{alpha}{numeric scalar in (0, 1)} +\item{alp}{numeric scalar in (0, 1)} -\item{cluster}{character scalar or NULL} +\item{clustervars}{character scalar or NULL} \item{control_group}{character scalar, already matched via \code{match.arg}} -\item{n_bootstrap}{non-negative integer} +\item{biters}{non-negative integer (internal bootstrap iterations)} \item{anticipation}{non-negative integer} diff --git a/tests/testthat/test-edid-aggregate.R b/tests/testthat/test-edid-aggregate.R index 45390f8..62f9e93 100644 --- a/tests/testthat/test-edid-aggregate.R +++ b/tests/testthat/test-edid-aggregate.R @@ -4,7 +4,8 @@ library(testthat) fit_one_cohort <- function(seed = 42, n_treat = 30, n_never = 30, n_periods = 5) { df <- make_panel_1cohort(n_treat = n_treat, n_never = n_never, n_periods = n_periods, seed = seed) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, store_eif = TRUE, covariates = NULL) list(fit = fit, panel = panel) @@ -63,7 +64,8 @@ test_that("aggregate_event_study_edid() returns a list with entries for each rel # ============================================================ test_that("aggregate_group_edid() returns one entry per treated cohort", { df <- make_panel_2cohort() - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, store_eif = TRUE, covariates = NULL) grp <- aggregate_group_edid(fit$cells, fit$eif_matrix, fit$cell_index, panel, alpha = 0.05) diff --git a/tests/testthat/test-edid-bootstrap.R b/tests/testthat/test-edid-bootstrap.R index e234385..5dc8500 100644 --- a/tests/testthat/test-edid-bootstrap.R +++ b/tests/testthat/test-edid-bootstrap.R @@ -117,7 +117,8 @@ test_that("compute_bootstrap_stats_edid() p_value in [0, 1]", { # ============================================================ test_that("run_multiplier_bootstrap_edid() runs without error and returns bootstrap draws", { df <- make_panel_1cohort(seed = 77) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") fit <- fit_edid_cells(panel, pt_assumption = "all", alpha = 0.05, store_eif = TRUE, covariates = NULL) boot_res <- run_multiplier_bootstrap_edid( diff --git a/tests/testthat/test-edid-inference.R b/tests/testthat/test-edid-inference.R index d25bfff..6ca1d48 100644 --- a/tests/testthat/test-edid-inference.R +++ b/tests/testthat/test-edid-inference.R @@ -40,8 +40,9 @@ test_that("cluster_aggregate_edid() sums EIF within clusters correctly", { test_that("cluster_aggregate_edid() SE with clustering differs from iid SE", { df <- make_panel_clustered(seed = 42) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat", - cluster = "cluster_id") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", + clustervars = "cluster_id") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "post") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") diff --git a/tests/testthat/test-edid-integration.R b/tests/testthat/test-edid-integration.R index 5274473..1516bd2 100644 --- a/tests/testthat/test-edid-integration.R +++ b/tests/testthat/test-edid-integration.R @@ -6,14 +6,14 @@ library(testthat) test_that("edid() returns an edid_fit object on one-cohort panel", { df <- make_panel_1cohort(seed = 42) fit <- edid( - data = df, - outcome = "outcome", - unit = "unit", - time = "time", - first_treat = "first_treat", + data = df, + yname = "outcome", + idname = "unit", + tname = "time", + gname = "first_treat", pt_assumption = "all", - aggregate = "all", - n_bootstrap = 0L + aggregate = "all", + bstrap = FALSE ) expect_s3_class(fit, "edid_fit") }) @@ -23,8 +23,9 @@ test_that("edid() returns an edid_fit object on one-cohort panel", { # ============================================================ test_that("edid_fit contains all required top-level fields", { df <- make_panel_1cohort(seed = 1) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - pt_assumption = "all", aggregate = "all", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + pt_assumption = "all", aggregate = "all", bstrap = FALSE) required_fields <- c("call", "pt_assumption", "control_group", "alpha", "n", "T_periods", "treatment_groups", "anticipation", "inference_type", "cells", "att_gt", "overall", "event_study", "group") @@ -39,8 +40,8 @@ test_that("edid_fit contains all required top-level fields", { # ============================================================ test_that("edid_fit$att_gt is a data.frame with required columns", { df <- make_panel_1cohort(seed = 2) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - aggregate = "all", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all", bstrap = FALSE) expect_s3_class(fit$att_gt, "data.frame") expected_cols <- c("group", "time", "att", "se", "ci_lower", "ci_upper", "p_value", "is_pre") for (col in expected_cols) { @@ -53,8 +54,8 @@ test_that("edid_fit$att_gt is a data.frame with required columns", { # ============================================================ test_that("edid() post-treatment ATT estimates are finite", { df <- make_panel_1cohort(seed = 3) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - aggregate = "all", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all", bstrap = FALSE) post_cells <- fit$att_gt[!fit$att_gt$is_pre, ] expect_true(all(is.finite(post_cells$att))) }) @@ -64,20 +65,22 @@ test_that("edid() post-treatment ATT estimates are finite", { # ============================================================ test_that("edid() PT-Post overall ATT close to 2 for ATT=2 DGP (large sample)", { df <- make_panel_1cohort(n_treat = 300, n_never = 300, n_periods = 5, seed = 555) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", pt_assumption = "post", aggregate = "overall", - n_bootstrap = 0L) + bstrap = FALSE) # True ATT = 2; allow generous tolerance for finite samples expect_equal(fit$overall$att, 2, tolerance = 0.4) }) test_that("edid() PT-All overall ATT close to 2 for ATT=2 DGP (large sample)", { df <- make_panel_1cohort(n_treat = 300, n_never = 300, n_periods = 5, seed = 666) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", pt_assumption = "all", aggregate = "overall", - n_bootstrap = 0L) + bstrap = FALSE) expect_equal(fit$overall$att, 2, tolerance = 0.5) }) @@ -86,19 +89,22 @@ test_that("edid() PT-All overall ATT close to 2 for ATT=2 DGP (large sample)", { # ============================================================ test_that("print.edid_fit() runs without error", { df <- make_panel_1cohort(seed = 4) - fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all") expect_output(print(fit)) }) test_that("summary.edid_fit() runs without error", { df <- make_panel_1cohort(seed = 5) - fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all") expect_output(summary(fit)) }) test_that("coef.edid_fit() returns named numeric vector for att_gt", { df <- make_panel_1cohort(seed = 6) - fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all") coefs <- coef(fit, which = "att_gt") expect_true(is.numeric(coefs)) expect_true(length(coefs) > 0) @@ -107,7 +113,8 @@ test_that("coef.edid_fit() returns named numeric vector for att_gt", { test_that("vcov.edid_fit() returns a numeric matrix", { df <- make_panel_1cohort(seed = 7, n_treat = 40, n_never = 40) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all", store_eif = TRUE) V <- vcov(fit, which = "att_gt") expect_true(is.matrix(V)) @@ -116,7 +123,8 @@ test_that("vcov.edid_fit() returns a numeric matrix", { test_that("as.data.frame.edid_fit() returns a data.frame", { df <- make_panel_1cohort(seed = 8) - fit <- edid(df, "outcome", "unit", "time", "first_treat", aggregate = "all") + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", aggregate = "all") df_out <- as.data.frame(fit) expect_s3_class(df_out, "data.frame") }) @@ -126,16 +134,18 @@ test_that("as.data.frame.edid_fit() returns a data.frame", { # ============================================================ test_that("edid() two-cohort staggered panel produces two groups in group aggregation", { df <- make_panel_2cohort(seed = 200) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - pt_assumption = "all", aggregate = "all", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + pt_assumption = "all", aggregate = "all", bstrap = FALSE) expect_equal(length(fit$group), 2L) }) test_that("edid() two-cohort: group ATTs are near true values 1.5 and 2.5 (large sample)", { df <- make_panel_2cohort(n_g3 = 200, n_g5 = 200, n_never = 200, n_periods = 7, seed = 300) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - pt_assumption = "post", aggregate = "group", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + pt_assumption = "post", aggregate = "group", bstrap = FALSE) atts <- sapply(fit$group, function(x) x$att) # Group g=3 should be near 1.5; group g=5 near 2.5 expect_equal(unname(sort(atts)), c(1.5, 2.5), tolerance = 0.6) @@ -144,21 +154,23 @@ test_that("edid() two-cohort: group ATTs are near true values 1.5 and 2.5 (large # ============================================================ # 9.8 Bootstrap integration # ============================================================ -test_that("edid() with n_bootstrap > 0 returns bootstrap field in edid_fit", { +test_that("edid() with bstrap=TRUE returns bootstrap field in edid_fit", { df <- make_panel_1cohort(seed = 42) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", pt_assumption = "post", aggregate = "overall", - n_bootstrap = 50L, bootstrap_weights = "rademacher", - seed = 42L) + bstrap = TRUE, biters = 50L, bootstrap_weights = "rademacher", + seed = 42L) expect_false(is.null(fit$bootstrap)) expect_equal(fit$bootstrap$n_bootstrap, 50L) }) test_that("edid() bootstrap SE differs from analytical SE (not identical)", { df <- make_panel_1cohort(n_treat = 40, n_never = 40, seed = 99) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", pt_assumption = "post", aggregate = "overall", - n_bootstrap = 200L, seed = 42L) + bstrap = TRUE, biters = 200L, seed = 42L) # Bootstrap SE and analytical SE are related but not identical # Both should be finite and positive expect_true(is.finite(fit$overall$se)) @@ -168,12 +180,13 @@ test_that("edid() bootstrap SE differs from analytical SE (not identical)", { # ============================================================ # 9.9 Clustered edid() # ============================================================ -test_that("edid() with cluster argument produces finite clustered SEs", { +test_that("edid() with clustervars argument produces finite clustered SEs", { df <- make_panel_clustered(seed = 55) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - cluster = "cluster_id", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + clustervars = "cluster_id", pt_assumption = "post", aggregate = "overall", - n_bootstrap = 0L) + bstrap = FALSE) expect_true(is.finite(fit$overall$se)) expect_true(fit$overall$se > 0) }) @@ -185,8 +198,8 @@ test_that("edid() errors with clear message when covariates are supplied", { df <- make_panel_1cohort(seed = 1) df$x1 <- rnorm(nrow(df)) expect_error( - edid(df, "outcome", "unit", "time", "first_treat", - covariates = "x1"), + edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", covariates = "x1"), regexp = "covariate|not yet implemented" ) }) @@ -197,8 +210,8 @@ test_that("edid() errors with clear message when covariates are supplied", { test_that("edid() errors with clear message when survey_design is supplied", { df <- make_panel_1cohort(seed = 1) expect_error( - edid(df, "outcome", "unit", "time", "first_treat", - survey_design = list(fake = TRUE)), + edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", survey_design = list(fake = TRUE)), regexp = "survey|not yet implemented" ) }) @@ -208,7 +221,8 @@ test_that("edid() errors with clear message when survey_design is supplied", { # ============================================================ test_that("edid() with store_eif=TRUE returns eif matrix of correct dimensions", { df <- make_panel_1cohort(n_treat = 20, n_never = 20, n_periods = 4, seed = 42) - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", store_eif = TRUE, aggregate = "all") expect_false(is.null(fit$eif)) # eif should be n x n_non_na_cells matrix @@ -224,7 +238,8 @@ test_that("edid() on minimal degenerate panel runs without error", { # PT-Post, g=2: baseline = 2-1-0 = 1 = period_1, so all cells have no valid pairs -> NA ATT # Should return result without error (all NA cells) expect_no_error({ - fit <- edid(df, "outcome", "unit", "time", "first_treat", + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", pt_assumption = "post", aggregate = "none") }) }) @@ -236,7 +251,8 @@ test_that("edid() errors loudly on unbalanced panel", { df <- make_panel_1cohort(seed = 1) df <- df[-1, ] # remove one row -> unbalanced expect_error( - edid(df, "outcome", "unit", "time", "first_treat"), + edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat"), regexp = "balanced|unbalanced" ) }) @@ -246,10 +262,27 @@ test_that("edid() errors loudly on unbalanced panel", { # ============================================================ test_that("edid() 95% CI contains 2 for large-n ATT=2 DGP", { df <- make_panel_1cohort(n_treat = 500, n_never = 500, n_periods = 5, seed = 1234) - fit <- edid(df, "outcome", "unit", "time", "first_treat", - pt_assumption = "post", aggregate = "overall", n_bootstrap = 0L) + fit <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + pt_assumption = "post", aggregate = "overall", bstrap = FALSE) ci_lo <- fit$overall$ci_lower ci_hi <- fit$overall$ci_upper expect_true(ci_lo < 2 && ci_hi > 2, info = paste("CI:", ci_lo, "-", ci_hi, "does not contain 2")) }) + +# ============================================================ +# 9.16 G=0 auto-conversion (att_gt convention) +# ============================================================ +test_that("edid() accepts G=0 for never-treated and auto-converts to Inf", { + df <- make_panel_1cohort(seed = 42) + # Replace Inf with 0 to simulate att_gt convention + df$first_treat_0 <- ifelse(df$first_treat == Inf, 0, df$first_treat) + fit_0 <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat_0", + pt_assumption = "post", aggregate = "overall", bstrap = FALSE) + fit_inf <- edid(df, yname = "outcome", idname = "unit", tname = "time", + gname = "first_treat", + pt_assumption = "post", aggregate = "overall", bstrap = FALSE) + expect_equal(fit_0$overall$att, fit_inf$overall$att, tolerance = 1e-10) +}) diff --git a/tests/testthat/test-edid-nocov.R b/tests/testthat/test-edid-nocov.R index a90c636..4ee174a 100644 --- a/tests/testthat/test-edid-nocov.R +++ b/tests/testthat/test-edid-nocov.R @@ -5,7 +5,8 @@ library(testthat) # ============================================================ test_that("compute_omega_star_nocov_edid() returns H x H symmetric numeric matrix", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 1) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") H <- nrow(pairs) @@ -17,7 +18,8 @@ test_that("compute_omega_star_nocov_edid() returns H x H symmetric numeric matri test_that("compute_omega_star_nocov_edid() is positive semi-definite (eigenvalues >= 0)", { df <- make_panel_1cohort(n_treat = 40, n_never = 40, n_periods = 5, seed = 2) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") @@ -30,7 +32,8 @@ test_that("compute_omega_star_nocov_edid() is positive semi-definite (eigenvalue # ============================================================ test_that("compute_omega_star_nocov_edid() returns 1x1 matrix under PT-Post", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 3) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "post") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") @@ -44,7 +47,8 @@ test_that("compute_omega_star_nocov_edid() returns 1x1 matrix under PT-Post", { # ============================================================ test_that("compute_efficient_weights_edid() weights sum to 1", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 4) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") @@ -79,7 +83,8 @@ test_that("compute_efficient_weights_edid() uses pseudoinverse fallback for sing test_that("compute_efficient_weights_edid() returns numeric vector with no NA or NaN", { df <- make_panel_1cohort(n_treat = 25, n_never = 25, n_periods = 5, seed = 5) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") @@ -92,7 +97,8 @@ test_that("compute_efficient_weights_edid() returns numeric vector with no NA or # ============================================================ test_that("compute_generated_outcomes_nocov_edid() returns length-H finite vector", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 6) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "all") @@ -102,7 +108,8 @@ test_that("compute_generated_outcomes_nocov_edid() returns length-H finite vecto test_that("compute_generated_outcomes_nocov_edid() PT-Post returns length-1 vector", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 7) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "post") y_hat <- compute_generated_outcomes_nocov_edid(3L, 4L, pairs, panel, "post") @@ -112,7 +119,8 @@ test_that("compute_generated_outcomes_nocov_edid() PT-Post returns length-1 vect test_that("compute_generated_outcomes_nocov_edid() ATT=2 panel: generated outcome close to 2 for post period", { # Panel with known ATT=2 (from make_panel_1cohort default) df <- make_panel_1cohort(n_treat = 200, n_never = 200, n_periods = 5, seed = 99) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "post") y_hat <- compute_generated_outcomes_nocov_edid(3L, 3L, pairs, panel, "post") @@ -125,7 +133,8 @@ test_that("compute_generated_outcomes_nocov_edid() ATT=2 panel: generated outcom # ============================================================ test_that("compute_eif_nocov_edid() returns length-n finite vector", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 8) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") n <- panel$n pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") @@ -140,7 +149,8 @@ test_that("compute_eif_nocov_edid() returns length-n finite vector", { test_that("compute_eif_nocov_edid() has zero mean (up to numerical precision)", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 9) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") @@ -153,7 +163,8 @@ test_that("compute_eif_nocov_edid() has zero mean (up to numerical precision)", test_that("compute_eif_nocov_edid() PT-Post: EIF has zero mean", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 10) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "post") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "post") @@ -166,7 +177,8 @@ test_that("compute_eif_nocov_edid() PT-Post: EIF has zero mean", { test_that("compute_eif_nocov_edid() sum of squared EIF is positive (non-degenerate)", { df <- make_panel_1cohort(n_treat = 30, n_never = 30, n_periods = 5, seed = 11) - panel <- prepare_edid_panel(df, "outcome", "unit", "time", "first_treat") + panel <- prepare_edid_panel(df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat") pairs <- enumerate_valid_pairs_edid(3L, panel$treatment_groups, panel$time_periods, panel$period_1, "all") omega <- compute_omega_star_nocov_edid(3L, 4L, pairs, panel, "all") diff --git a/tests/testthat/test-edid-validate.R b/tests/testthat/test-edid-validate.R index 2ccba9b..f5fe169 100644 --- a/tests/testthat/test-edid-validate.R +++ b/tests/testthat/test-edid-validate.R @@ -8,11 +8,11 @@ test_that("validate_edid_inputs() passes on valid one-cohort panel", { df <- make_panel_1cohort() expect_silent( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ) ) }) @@ -21,11 +21,11 @@ test_that("validate_edid_inputs() passes on two-cohort panel", { df <- make_panel_2cohort() expect_silent( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "post", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 100L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 100L, anticipation = 0L, survey_design = NULL ) ) }) @@ -33,29 +33,29 @@ test_that("validate_edid_inputs() passes on two-cohort panel", { # ============================================================ # 3.2 Missing column names # ============================================================ -test_that("validate_edid_inputs() errors on missing outcome column", { +test_that("validate_edid_inputs() errors on missing yname column", { df <- make_panel_1cohort() expect_error( validate_edid_inputs( - data = df, outcome = "y_outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "y_outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "y_outcome" ) }) -test_that("validate_edid_inputs() errors on missing time column", { +test_that("validate_edid_inputs() errors on missing tname column", { df <- make_panel_1cohort() expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "t_var", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "t_var", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "t_var" ) @@ -69,11 +69,11 @@ test_that("validate_edid_inputs() errors on character outcome column", { df$outcome <- as.character(df$outcome) expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ) ) }) @@ -86,11 +86,11 @@ test_that("validate_edid_inputs() errors on Inf outcome", { df$outcome[1] <- Inf expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "finite|non-finite|Inf" ) @@ -101,11 +101,11 @@ test_that("validate_edid_inputs() errors on NA outcome", { df$outcome[5] <- NA_real_ expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ) ) }) @@ -118,11 +118,11 @@ test_that("validate_edid_inputs() errors on unbalanced panel", { df_unbal <- df[-1, ] # drop one row -> unit 1 missing period 1 expect_error( validate_edid_inputs( - data = df_unbal, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df_unbal, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "balanced|unbalanced" ) @@ -131,16 +131,16 @@ test_that("validate_edid_inputs() errors on unbalanced panel", { # ============================================================ # 3.6 Duplicate (unit, time) rows # ============================================================ -test_that("validate_edid_inputs() errors on duplicate (unit, time) rows", { +test_that("validate_edid_inputs() errors on duplicate (idname, tname) rows", { df <- make_panel_1cohort() df_dup <- rbind(df, df[1, ]) # duplicate first row expect_error( validate_edid_inputs( - data = df_dup, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df_dup, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "[Dd]uplicate" ) @@ -155,11 +155,11 @@ test_that("validate_edid_inputs() errors on non-absorbing treatment", { df$first_treat[df$unit == 1 & df$time == 2] <- 4L expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "absorbing|time-varying|constant" ) @@ -168,19 +168,19 @@ test_that("validate_edid_inputs() errors on non-absorbing treatment", { # ============================================================ # 3.8 No never-treated units # ============================================================ -test_that("validate_edid_inputs() errors when no never-treated units and control_group='never_treated'", { +test_that("validate_edid_inputs() errors when no never-treated units and control_group='nevertreated'", { df <- make_panel_1cohort() # relabel all never-treated as cohort 4 df$first_treat[df$first_treat == Inf] <- 4L expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), - regexp = "never.treated|never_treated" + regexp = "never.treated|nevertreated" ) }) @@ -192,11 +192,11 @@ test_that("validate_edid_inputs() errors when covariates supplied (stub)", { df$x1 <- rnorm(nrow(df)) expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = "x1", pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "covariate|not yet implemented" ) @@ -209,11 +209,11 @@ test_that("validate_edid_inputs() errors when survey_design supplied (stub)", { df <- make_panel_1cohort() expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, + alp = 0.05, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = list(strata = "fake") ), regexp = "survey|not yet implemented" @@ -221,26 +221,26 @@ test_that("validate_edid_inputs() errors when survey_design supplied (stub)", { }) # ============================================================ -# 3.11 Invalid alpha +# 3.11 Invalid alp # ============================================================ -test_that("validate_edid_inputs() errors on alpha outside (0,1)", { +test_that("validate_edid_inputs() errors on alp outside (0,1)", { df <- make_panel_1cohort() expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 1.5, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 1.5, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ) ) expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0, cluster = NULL, control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0, clustervars = NULL, control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ) ) }) @@ -254,11 +254,11 @@ test_that("validate_edid_inputs() errors on time-varying cluster variable", { df$cluster_id[df$unit == 1 & df$time == 2] <- 999L expect_error( validate_edid_inputs( - data = df, outcome = "outcome", unit = "unit", - time = "time", first_treat = "first_treat", + data = df, yname = "outcome", idname = "unit", + tname = "time", gname = "first_treat", covariates = NULL, pt_assumption = "all", - alpha = 0.05, cluster = "cluster_id", control_group = "never_treated", - n_bootstrap = 0L, anticipation = 0L, survey_design = NULL + alp = 0.05, clustervars = "cluster_id", control_group = "nevertreated", + biters = 0L, anticipation = 0L, survey_design = NULL ), regexp = "cluster|time.invariant|time-invariant" ) From 10af0873b0ccf49a4e5b35e4b8dc2648d115b6ea Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Tue, 14 Apr 2026 12:00:39 -0400 Subject: [PATCH 06/12] builder: fix PT-All pair enumeration -- remove never-treated as comparison cohort Replaces the PT-All loop in enumerate_valid_pairs_edid() to use only treated cohorts as comparison cohorts (never-treated appears only as the time control inside each moment). Self-pairs (gp==target_g) include period_1 as a valid tpre (degenerate CS DiD); cross-pairs exclude it. This eliminates T-1 redundant gp=Inf rows, resolves near-singular Omega, and produces a correctly-specified analytical Omega for PT-All. Also removes dead gp=Inf branches in compute_omega_star_nocov_edid(), compute_generated_outcomes_nocov_edid(), and compute_eif_nocov_edid() that handled the now-impossible Inf comparison cohort case. PT-Post paths are unchanged. ATT estimates match author's reference to < 1e-10; pair count for cell (g=3, t=any) on 10-period 3-cohort data is 13 (was: 10 finite + 9 redundant Inf). Co-Authored-By: Claude Sonnet 4.6 --- R/edid-nocov.R | 57 +++++++++++++------------------------------------- R/edid-pairs.R | 40 ++++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 57 deletions(-) diff --git a/R/edid-nocov.R b/R/edid-nocov.R index 1033c9d..9042e9d 100644 --- a/R/edid-nocov.R +++ b/R/edid-nocov.R @@ -83,15 +83,9 @@ compute_omega_star_nocov_edid <- function( gp_val <- unique_gp_tpre$gp[rr] tp_val <- unique_gp_tpre$tpre[rr] key <- paste0(gp_val, "_", tp_val) - if (is.finite(gp_val)) { - mask_gp <- panel_obj$cohort_masks[[as.character(gp_val)]] - col_pre <- .col(panel_obj, tp_val) - delta_gp_cache[[key]] <- ow[mask_gp, col_pre] - ow[mask_gp, col_1] - } else { - # Never-treated: delta_{inf, tpre, 1} = Y_{tpre} - Y_{period_1} - col_pre <- .col(panel_obj, tp_val) - delta_gp_cache[[key]] <- ow[mask_inf, col_pre] - ow[mask_inf, col_1] - } + mask_gp <- panel_obj$cohort_masks[[as.character(gp_val)]] + col_pre <- .col(panel_obj, tp_val) + delta_gp_cache[[key]] <- ow[mask_gp, col_pre] - ow[mask_gp, col_1] } omega <- matrix(0, nrow = H, ncol = H) @@ -100,11 +94,7 @@ compute_omega_star_nocov_edid <- function( gp_j <- pairs$gp[j] tpre_j <- pairs$tpre[j] key_j <- paste0(gp_j, "_", tpre_j) - n_gp_j <- if (is.finite(gp_j)) { - sum(panel_obj$cohort_masks[[as.character(gp_j)]]) - } else { - n_inf - } + n_gp_j <- sum(panel_obj$cohort_masks[[as.character(gp_j)]]) delta_inf_j <- delta_inf_cache[[as.character(tpre_j)]] delta_gp_j <- delta_gp_cache[[key_j]] @@ -116,11 +106,7 @@ compute_omega_star_nocov_edid <- function( gp_k <- pairs$gp[k] tpre_k <- pairs$tpre[k] key_k <- paste0(gp_k, "_", tpre_k) - n_gp_k <- if (is.finite(gp_k)) { - sum(panel_obj$cohort_masks[[as.character(gp_k)]]) - } else { - n_inf - } + n_gp_k <- sum(panel_obj$cohort_masks[[as.character(gp_k)]]) delta_inf_k <- delta_inf_cache[[as.character(tpre_k)]] delta_gp_k <- delta_gp_cache[[key_k]] @@ -239,13 +225,8 @@ compute_generated_outcomes_nocov_edid <- function( term_inf <- mean(ow[mask_inf, col_t] - ow[mask_inf, col_pre]) - if (is.finite(gp_j)) { - mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] - term_gp <- mean(ow[mask_gp, col_pre] - ow[mask_gp, col_1]) - } else { - # gp = Inf: comparison is never-treated baseline change - term_gp <- mean(ow[mask_inf, col_pre] - ow[mask_inf, col_1]) - } + mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] + term_gp <- mean(ow[mask_gp, col_pre] - ow[mask_gp, col_1]) y_hat[j] <- term_g - term_inf - term_gp } @@ -329,23 +310,13 @@ compute_eif_nocov_edid <- function( eif[mask_inf] <- eif[mask_inf] - w_j * (delta_inf_t_pre - mean_inf_t_pre) / pi_inf - # Comparison cohort contribution (subtract, only if gp_j is finite) - if (is.finite(gp_j)) { - mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] - pi_gp <- panel_obj$cohort_fractions[[as.character(gp_j)]] - delta_gp_pre_base <- ow[mask_gp, col_pre] - ow[mask_gp, col_base] - mean_gp_pre_base <- mean(delta_gp_pre_base) - eif[mask_gp] <- eif[mask_gp] - - w_j * (delta_gp_pre_base - mean_gp_pre_base) / pi_gp - } - # If gp_j == Inf: the comparison cohort is never-treated itself, - # which contributes only through the -delta_inf term above. - # The baseline change delta_{inf, tpre, 1} contributes to the - # never-treated units with an additional term when gp_j==Inf in PT-All. - # Per the EIF formula: phi_{ij} for gp_j==Inf has no 3rd indicator - # term (since I(G_i=gp_j) == I(G_i=Inf) which is already handled - # in the never-treated contribution above when we subtract the mean). - # No additional action needed here. + # Comparison cohort contribution (subtract) + mask_gp <- panel_obj$cohort_masks[[as.character(gp_j)]] + pi_gp <- panel_obj$cohort_fractions[[as.character(gp_j)]] + delta_gp_pre_base <- ow[mask_gp, col_pre] - ow[mask_gp, col_base] + mean_gp_pre_base <- mean(delta_gp_pre_base) + eif[mask_gp] <- eif[mask_gp] - + w_j * (delta_gp_pre_base - mean_gp_pre_base) / pi_gp } } diff --git a/R/edid-pairs.R b/R/edid-pairs.R index bfa991d..2ec2a07 100644 --- a/R/edid-pairs.R +++ b/R/edid-pairs.R @@ -10,9 +10,15 @@ #' or a 0-row data.frame if that pre-period does not exist in \code{time_periods} or #' equals \code{period_1}. #' -#' Under \strong{PT-All}: returns all \code{(gp, tpre)} pairs where \code{gp} ranges -#' over all cohorts (including never-treated) and \code{tpre} is a valid pre-period -#' strictly less than the effective treatment start of \code{gp}, excluding \code{period_1}. +#' Under \strong{PT-All}: iterates over treated cohorts \code{g'} only (the +#' never-treated group is the time control inside every moment, not a comparison +#' cohort). For \code{g' == target_g}: valid \code{tpre} are all periods strictly +#' less than \code{g' - anticipation}, including \code{period_1} (this is the +#' degenerate CS DiD moment whose comparison-cohort EIF term is identically zero). +#' For \code{g' != target_g}: valid \code{tpre} are periods strictly between +#' \code{period_1} and \code{g' - anticipation} (exclusive on both ends). +#' Returns a 0-row data.frame if no valid pairs exist (e.g., single cohort with +#' only one pre-period equal to \code{period_1}). #' #' @param target_g scalar: treatment cohort being estimated #' @param treatment_groups sorted numeric vector of all finite cohort values @@ -48,22 +54,28 @@ enumerate_valid_pairs_edid <- function( } # ------------------------------------------------------------------------- - # PT-All: loop over all candidate comparison cohorts + # PT-All: loop over treated cohorts only (never-treated is NOT a comparison + # cohort; it appears only as the time control E[Y_inf(t)-Y_inf(tpre)] inside + # each moment). + # + # For g' == target_g: valid tpre = {s : s < eff_start(g')} + # -- INCLUDES period_1 (degenerate CS DiD moment; comparison EIF = 0) + # For g' != target_g: valid tpre = {s : period_1 < s < eff_start(g')} + # -- EXCLUDES period_1 (non-degenerate moments only) # ------------------------------------------------------------------------- - candidate_gps <- c(treatment_groups, never_treated_val) - out_gp <- numeric(0L) out_tpre <- numeric(0L) - for (gp in candidate_gps) { - if (is.finite(gp)) { - # Finite comparison cohort: effective treatment start = gp - anticipation - eff_start <- gp - anticipation - # Valid tpre: strictly less than eff_start, not period_1 - valid_tpre <- time_periods[time_periods < eff_start & time_periods != period_1] + for (gp in treatment_groups) { + eff_start <- gp - anticipation + if (gp == target_g) { + # Self-pair: include period_1 + valid_tpre <- time_periods[time_periods < eff_start] } else { - # Never-treated: all periods except period_1 are valid - valid_tpre <- time_periods[time_periods != period_1] + # Cross-pair: exclude period_1 + valid_tpre <- time_periods[ + time_periods > period_1 & time_periods < eff_start + ] } if (length(valid_tpre) > 0L) { out_gp <- c(out_gp, rep(gp, length(valid_tpre))) From c699fbcf7822b54fabef4f5c9ca032ef7922ec3f Mon Sep 17 00:00:00 2001 From: Marcelo Ortiz Date: Fri, 17 Apr 2026 14:38:38 -0400 Subject: [PATCH 07/12] adding edid estimation feature without covariates --- CSX2026.pdf | Bin 0 -> 17741742 bytes EDID_implemention.md | 697 +++++ Efficient_DiD.pdf | Bin 0 -> 411927 bytes IMPLEMENTATION_PLAN.md | 907 ++++++ METHODOLOGY_REVIEW.md | 803 +++++ R/edid-data.R | 6 +- R/edid-methods.R | 4 +- R/edid-validate.R | 4 +- R/edid.R | 4 +- Rplots.pdf | Bin 0 -> 7530 bytes audit.md | 354 +++ benchmark/compare_author_vs_edid.R | 333 ++ benchmark/data/diffdiff_panel.csv | 3001 +++++++++++++++++++ benchmark/data/py_edid_all_es.csv | 14 + benchmark/data/py_edid_all_grp.csv | 4 + benchmark/data/py_edid_all_gt.csv | 28 + benchmark/data/py_edid_all_overall.csv | 2 + benchmark/edid_sim_original.R | 404 +++ benchmark/generate_diffdiff_benchmark.py | 110 + compare_att_gt_edid.R | 178 +- comprehension.md | 128 + implementation.md | 107 + mailbox.md | 69 + man/edid.Rd | 4 +- man/prepare_edid_panel.Rd | 2 +- spec.md | 308 ++ test-spec.md | 769 +++++ tests/testthat/test-edid-pairs-validation.R | 377 +++ tests/testthat/test-edid-pairs.R | 52 +- 29 files changed, 8637 insertions(+), 32 deletions(-) create mode 100644 CSX2026.pdf create mode 100644 EDID_implemention.md create mode 100644 Efficient_DiD.pdf create mode 100644 IMPLEMENTATION_PLAN.md create mode 100644 METHODOLOGY_REVIEW.md create mode 100644 Rplots.pdf create mode 100644 audit.md create mode 100644 benchmark/compare_author_vs_edid.R create mode 100644 benchmark/data/diffdiff_panel.csv create mode 100644 benchmark/data/py_edid_all_es.csv create mode 100644 benchmark/data/py_edid_all_grp.csv create mode 100644 benchmark/data/py_edid_all_gt.csv create mode 100644 benchmark/data/py_edid_all_overall.csv create mode 100644 benchmark/edid_sim_original.R create mode 100644 benchmark/generate_diffdiff_benchmark.py create mode 100644 comprehension.md create mode 100644 implementation.md create mode 100644 mailbox.md create mode 100644 spec.md create mode 100644 test-spec.md create mode 100644 tests/testthat/test-edid-pairs-validation.R diff --git a/CSX2026.pdf b/CSX2026.pdf new file mode 100644 index 0000000000000000000000000000000000000000..251923a9418758bbc486daee8edbdfc1f5073254 GIT binary patch literal 17741742 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�Dj^_&?vDd{CyLk`uoxp83IWAnaex^}ECdh7 z03{$1K!G?s0*y5?LIB+wZiK*qe)EO_5;P79Tw_33U;qLkhBz3EuqZqRj3b~4STI13 zfB{AWFwS9s>wtp@3{W*54?$zFAS4(E$0LBg1_J7X1Kkb}hoJG;-`58S9ErmL)xyyj zJPwTk&agug;79;A9EHU}jIc;34v$A8jf^080vhlQ1Hxc%1fVo143EI0uvi$73-B5^ zP7N3pU@!)OL1Te#jE16(ut1GK2$YH;V9~(k0B;0%fCa`OU@hP~mS6J{8&V6>*-N9a`B`Z3zls_~xTZGS-WFz$UZ0>Og2`ESAVGclX}U z$kpl^Rzkh0YXg4f=D%!yynDCU>4TnVj1BkuWt}V0pTu2EleE(4fS=AlCB->9-AYTc zP`g6cnRZ!LX7`Hbyi?XJTx@2v@K4TFR(x;XY&_xB{W-(J{E9Y$HsUdy?Tr(sxn7>} zrmH_`uKLa}uLb*oQEyq#W_HBqEnMS0-2U~nu8(6AXZ8aEOP?6(ruDfON+1UIf&!Ph z`zKb77eY3#+P7yiYUahy-|R1ix<<#e$QH#8mo1ytuq?f4FnyuKVWLiaNpA*t&*p zOG|IrLiD`-VE8HLxQ;d5HND=Hf!>PZ^Pf4F)Wlkb3hj+Wt(?!VCp{E1$D8N*J{_V+ zU!b_I(3OmF=cp#vW#`JIV;CEW=)ECeagi>1p(Wb3MtW0p(4sM^RJ{9BpyG`_M@Az%p&Y*)|@*_X!O1x_F3)Ba7v1d25Dd4 z4#Dr=G+3_oa_{Q*HYo^vWg(JR`P}Iyg>^sLt7BN3Yu!1TLe$et%rNf@&cUJ3;IKOO zLA4bhosSz?>txj@-`?&y$9YKih$hFoYnKBptp^L3+?xzo^EnG^@4APcU@KP+?SJif z%|DbhbbH9fI9KOVbOUfEo#z)ROiYU0{*TWuV&nJiR&T(zVn`geXsTA33#b=1_to{& zv2!^FCEcanr9Gv?3xfsTI6|N|%i-xdjLWAxUj&ikxG#<;b@~mE)}pI6&$c_RSD~Ic z$0DCRr!2*b>C>C4LnGa+HMsoINLB&xc6>7S6zw((nf%#)w$4Jbak zVi_ZKwr?|#_&7RkJl{OoxYL zdUF^%bh^sC>X-FSi_C=W=?Y()d5o0DOKf7;?e>t! z8x*}fY1~2Y`fzX4^Zgi_i_G5e5Q;b~yptI%LfU;k!0ki-djwmT8Ln4Uz+6~D-+a@; zq5Aa04d2x!yFMGMfTXQn(e9qU&`skYx{r5pS+mnDqHp*VwkZdE5-e1?b-Ymq-X;Tz zW**X#K5Nve&pjJkTZQsoT7U6WcG)!Hy@ZN_LhO zSmF8KI6#LSQoBooIuiDoHP=#p%ajZbKX2&S`4APRk~yL^JN*9R$(o#uhG33E3xf*Imi=!pzGZzuj{zg}Gyit#znAYm%3k!pvWmZZ$B@SF|J zYF!I?o3`>K6ZA)a;7ZEK711S+zMXaydrnh|XN7tGC#!FZUX@JVMGYcPytw0kUHVWm zib9B|of+2|iF}bu(LZ%#!na0e{}V7x;i)n2eVZhMRGjPV$lm6Ru9&Qhr%9mW4;>w* zgr{dJyK7~QhR;}@LHjxtN9hMF_Q;Qr6AQhc(?KXOMv(M#Y(6YaK6UEssVG%vRwjZWAF;Pi1 zH!#rjVRJlYWTn2jv-4TOpjDC$%amc#yVM@+1P#0-BfYOS*U{Z{B5kJ2+zB~$@XOKM zVeW?*-L%L`!fqGgrruX3q_HCx?|ru32=Yf~ia!_Ka%;77bI3l=Y9BN*v3`+Uoxx4P z>%Q3d)EbRFP33@#NsXIZ3A8Tnq(%Bldq@bBaf|HYr_6aH+n#r^mj7*>%P3hVf_d>5_eN+xzbz0tAy2N zI!N%mNRx^N`dohuXYX7>n$;(7dYmPjivj5~Zd5h5$&=?Un0Lj^aViLZ@$@bBm`?Uu zh7`SIfiaEz%n`u}+9ebG<%o}-!p3J ze?FT?pvR-ekrr#F@0TgeOMa5yv&YAtW^V3Dm75VElsofwTI(U-8v5k1`kJX?YdB-lgFi7L9Y4vWW_4um?WOo>NmX0@7=1)93jL`i<8a(T@uRzK+!l@Q5Q zJa0(S)`XOJ#W*g$mk~E2BtQRUiOPh5e#id6q1E-2qQrZT*}%t+=4)!QgKVDtZB1Mp zp9~D|4^Tc}9PJOM0QyrU^`#+p&q+-chhPRLk7>RG22`hM$sCJZ*jojdQOd%Vj}bHv z)LPc4ed688WT@9ZAZ4w=;qKf~TcdiiOG?fwtgO1Q`<9VSVP+~ZaAmuxe%})-=kDp7 zzeX63++s0&_MPq{e6A_1yjE_okvBc8PnvbxXj=6B%hfonWSLx^&srfrdM3j$w0P`| z35ieB#@qvTjl*_YUrWrUE^yfzOyvI_R%csI4KbW`l0KAN+hk*R9ILD)HDAr8xK{~G z;kOh7c9~Y~YCGxb7gDG>D{`}RGhg>h<%3bC4!(<9s8ny;)e~tP1D}+Ie{6I-RH*zO z66;CI<=;mW@XD#>j@m-z!>xsv%}`6`?nh~P;q(_PV-*qgFH=7ybj#IYagW!b-o zyh&a#eb;00hLYsz*^5ph(!(%_#;(ln<$|_O-d49DSj3u6!o%{5cf+~$MXEeTh65OB zAFs+5pR{aFEai(=|A;%(lM;UrzA0F-@QD4D_4(&M1&e|Mv{U4pa|v@j))h`d?Qhb~ z^xNw3cMtW31VKvf&F9ljk?gK&@jR7n;#lC%$l%^MRaVH|yMlhmlz!@U)l!ORDdo;X zR}+k|+KkQcjjG6(=bG+}ZVnplG@X#V?$$qtdRPdJMm8c=RT&poVNbvrf5XijL;q7ebb4QXN7v8 zsH7Eosm$)58hF9to(CCO1C}`8mo8Lw&{Cga@crIy-a;vTMmWMypwri3UvHn63;pW^ z=OxqixCuFlI}-#~ay42GK{T)8Xwf|`T?2zW8DpBBA1a0|cur}qEL&Z-r_TBYYI7@Q z{d1do$}5HZ4H-3i-SM;`9KM05pi}cNUi%kcp1D-G7;E65LsEoey`#$TWqy;)jH2-I zrcprS182q`TTBV0b7PKBvF+kTMA8KBV_we*&eot8mGq)PkgONi<7DmCS!-=|W3wrC zS{T1mVR#4GN)G+P!d-Yhi;A<&Vlv_4k@QNs51510ex3Rio8-`rrgh=`jC!>C?TU3} zEAJ!?r9g*JS@)Mvg8L$4ZOBYk=u$)?3H{a%?UI*A>Qt2pd~cMgcl6v8UDS;cU?p?R zTeT?%bQKP1Voaq$L#L*lfAb_8=>-R{L}IMp;kf84zy7+pz}aHQ;#v21*p25PhS`m7 zP6)bd=S7+6Gd;CeV&2#KytAI6FNpXHejk9&_EwIcn@A8FwWzUtcvVes3j4*TCTt5{ zO8(xzLtA#XbG9eL`!FKBZ;^C!Z&bd5^f333WBW%~)68SKjPM6Odnlgvjvp}S)SO=} zy-sb)&&iW7t3IoJwYId);&IHZV=T=#eEy~I@T{7P6_o1QgT^{C4FTz(rK+9AC!E8G z#36^SnR&-*Ql}I5F3vx;**nj=T5r~av-?qaqSYs>*3DmI5=J>V9MeN5yY*xIN5+pE zQJkRi%JZ-0PYx#tNL{>2{fr_InvD$ENN7^^F3WqeY5UeXYu0Wk-C4mcEa+w}?YMmV z8P@3$`;U&|gmh9zoYJ9NPF<}tY%4i;N##txr{1rP`SY3iIn&WmUIL6{nsEvi?}wg4@2>>PxzOd#8bZcZp@gAHY6AI zr1m)XI3p3xt~Hj%RaQ=2yRnA#3!f%3y0Tc`xWD0hW@Q#vxx0L0nP(>dr5d-9Ua9L$ zM;^S$>#~<+Jw4fQFT1YRRZeQ%&+F1*3t`;UQd;s|V-qgglIx|Oq7T0hc@#&n54}P~ z^~CcitQKXD-@iF`XEL{=j8xsT`ZUKJjO?sV&Ga-B(kYM~_R94256c3J)ZQ9XZVUAr zK8a2j?TgbiM;YwJkls{9^d8R)-nSW9Bk3lan$KnqElQz!+a?pKFxdkiIAWB@7n;KA zb}}C#5mp5ic6D)D+Nl{$+LhDOC)j=094?wzpxT)%%%65*++D0Eha<={_oMv8E2-rL zZwL_rFNig)pPZ(fxeEFLxT(*L zq%&8Y!=I)HR?__px7o27i#l_Eh%93b`t@ecFy~jb4c@6J(3DVNgjhQ5cK#QNNY9XT zg1>8_6x6ZmGV13(+hfP!zBKi$Guf=9eN)9yt(@QO0Q3YlJwC7=9{&J?YE<%Rn; zL%8zWT!lAhc^tOxQBM!6oSb|LhmAh$mAAaZ(>Vg;nj;MinLcw?+;aQf%Dxy^Wq zmshu9Xg4?dUP~%bddlUwYfaR2NyuY-Ldbv_m1_Zm9ap=a7m>u&(2p2>7@*?Nu%vxR z^NTU1=H;)Haj)s=R)t93T@t~X$A)bmbr*6DI@A>|hJhI7Dpi}4h4pRTu6jFas6ZL;1!#>HfOpqC(%cM8N{aLCfl?LJPRT9o2oMg6be*7GamdAJu z+~V+04q5C#@IAikZ}DZg)c4AubYS8@P7o%;Oe*h+qJAX1(9ktxlT=gxWOJT#)kU{F zN4$rJmimfTZxQ?p)#Cy7P3aOk^DFbFZ>y&^pKP-Bs+QM;3wJLdV+}qz_m@7pI&}Tr zkd;V$_Y6y3af$kv)%iU)Jtt@171H8`gSH82PcQ~nJ zag<5R>OXr{P<EwxX24lCB0ksjRX==~e?Bh$I<CgFv1?19NpNoE)!&#GfX!WXq?P!7;Fw>(^ZibtP5K?w`;`jo_}THC zppBFMh47_aU48mJ4j9VIetR_XR1mBuMZ-(o)q+G2qOZke!Css1YXd`7?vGE`w{=)Y zEH7UkDwoQpC=*SmSze5fnkdT-BP(QwI^3R(Q3~LpS6hFyUX!f7YU1X^wVTy#m_%1y z{wrwu7im>O!TI(MNYbKP*@K+?#dY@|xp}nLVSy(UY?MOt zTig*W`krOo{0?0pUz>lR*j&Qtp5g>Y$63B4 z?{&ZTnDXp=CC^CEiAko7dCdf?R1xYa>_h$%D>|zy;RBf_d%;_8QoU-vK6fGM#t-y4 z8rR+D>@KDpBGZj|Ed8wtSAJ{ovEkJyO1b4R5;9RS#s}H$evHd|&-+XNmnahKY{=w5$`ThzotoFiZr#4+I8gT}U?XQ?zhnluP zdoOvNBOZr$7^+=kQ?R0ZsL5Da9-OA~IS7TcsQh8&{lL}ynYr9|jQ=6;V29$%h5CVT zhD#&ywz&^?WSBoC$Z?z7f4dZPE|p`-R2eRM%1pkOZ_FldAnJ5Vd+q7g+nt%IQL$>X zdY6`PjczLPi7SpK-iPPRc7qcM0OQ5zm)I=$Ry z`Fx+?)QzWbC>dgv7@T+e*_ZJ|ol!aBo9(Zw%p{ra3QUaLdKU(mK1WZEe}DEF{eF;k zesLWUZ#*z3j|O`M;79sa!klEprKRN7a5ahM5hU(E*L;dz25!Ph+;&Aw1>UuoB!yCt zb45tXurnQfcd4bSh$CPjN2)k%QHNoUDiIuamW3sI1RN=ECpw z?~rp?IJ{HkPsIeA#Gm3{PiDK%0=x3){E|<2O#M{v0pr3f!k3c6`q>?&%i*yDv@UPe zDlb>;nKGFqPgJcGH&2G1F2&m8fu`Zw-3B|l9yUywL_l7sBf9Mb z)z$WCGkg8T$#N;Z5dN3qxtC>|ZL>$2PAAYziJdoZHC?Y@jZ;vFbEI=wD^q#xPxi-q?tL8-<)U;HA)=HD%)WBGyI^Y4Rpn||2yYxGLDFZB&zoD34V$ptwZ z7Z@nqFr`K{?@{Z62q>&BoHI4EuFz{U`oT2Ye7YPn*n_Rl zHdZ~*;#zs<5-a8%v-B ziMkfQc?B1dWC0=TreVh)r6j5q40NfV3ZO1N^5msOBssirp7(cEMa?G~ zv$e$N?pm>ZH%_^k@I&bPsO`Y{TIc)_8(psX1ol?LGox5*lKrcyo+-sy3Gtu0lDoEO zr<{;Uj5AMoom<$3#Lb;A6j@8~z-r8D65E@yn#nr>s~pnm#Ua zu~dzs68@`qn_`uzfa$7pAh;-8z`Ha&r0=HM;igPQHA9`4-FBV2|M#v&>ry>LWY1@o zp|A3C&f4=MwzjU7ebO>LOE&5ri}Rd2z)}Uf#|5_yF4Uf{*H4^3qdZk{t7svcN>;pl zfThEn3-_w#-s)(-&FW`~grIKcti-xuMY-^s$Ww@?U5!FgVJPdCBwP^9V*jS_twoRw zEP$JHaUp?w{>gX4kOuYMew|Ozq;tPyLlbWg?QSKIlKmXqP1 z7VR;AM&RCM@`DL;<|t!f3T>h4R2DZ2mD-}pJpqhpe3hM;utWdBL2udiQ*U3rkvMI;ny(`vm5p-L@UyJ4hQZzw9MHULJbpz2#MBV^v2Y!`{$;cwOA&I%-+c zgZ6-xMQ@$YT;^rrA|IWKov0)#G1>)_5!oZXx6#AfVi;b=@$PFrg|Ne{{UL{7ea74pznj*1y0a%&ZT)h@tP|4qWu~a z*pqsDzMBneS8z&iT1%LTKTjQ&{9WS4)~MgWFkBcp3|F-Z9B6LSG`A}rXmUVWt4-zf z``1=kd3)B1Y)J&(lzDB@1NzM4?Kub`ntUF zo`hn+r-^f7ORMMFxX3`zz?8=LboZ-e@_<*UIGP3_SQoT`Zp^xQxF0_6%(B%!6X)*! zX(&pp*+;rB{n=pBN_e=E;x96B36E-7BRck08doYZaoRW<4be}VJ zfztY{k*$wciTJp|*q7_CA*DZl{?XamTAWz4u*)XyG7p)}E&M)7dU8lbIp0Is_2Qa~ z!;V^8xVTNqw}ooCZRXX%iHzslAoZ{;KEK5?Zgbz4F3>QxP2Kj8d7jeuvc2q{oCBV^ zp+w<@=2P9qrP#haPqL|9k&so!Sv$&A#tZSGQAQbit|PK_jHq#*jx(CZs}dW9fobgR zysc>)eJdjAlPNf!@)J;s!M@58vaU7}XnjI6!!C>B9M^`yFY%f(sZvj;MTUSvbC&_# z)nP8n34F_Y&czd+TAyX(0~3@CB((TGmCav%M*f0d%PunF_Dx-y$@eT9u(>k=jZ78% zuZmHJ@SkpH%`dahK;?A1QTRe)teQ=(;kc}#@!7+OF+F6bPj!QO# zuL3U^f1aL@-J+VenO)@bLw?_ky4=tbU{AU`_t@T@5ikDQHjd2gqC?J3^##AnroApk zyYGBm7S(+oz6oG`*KqN9@}L~c>@}l9>yS*=xymWo0$4Tj9tL9@lkctyx_O!P&97x>=SW;N40%&8b^7VkAp-ipr>!{JvyH!8e#X#gFl2%{*E>T}4NRzecS6~rGSXj~li zZj4uQ{=rh`{AP9Re#ZBLp6S8*nN2jsx7PzhOvxS0#-8r)Zhym@Uy-`qzUr#!&s zrtx|G1fj9Mo0lEB;nTLZa^L$hsFT) znQ!bF;Ki>fgOUU#X`VYhW$0k#)B1(Ez3EBto1h+B4ysd6gc&R4QZ5HbGWQ;8FS&8Q ztP(Nyp!XT8tO^~q)8@kPcw)SMHS5W=j)jo9M4T`USgm7Gj?fTOsFo&)=UogMgXvDv zPSH9Hu-SLNyXnq%c8RuOKyXon!e_Q%hvK%2h@_}vc*Lk!#Un?KU(wHUA|*3xKeXqMqBi5a%NTX2*%-8*g4_46E(7nld3It#vGh|I}Lbe*I{PSDX_Bc z%_lg8W&$!vY>U6?Gr6azZ#a*5)Y!{@HK|419bFm&rl)Bcelk*L`)-d6;Enj^%vQ2$ z)p$AiBH0q1Wc=y2u4k*1UZqZ>Vfdb+nHV;{qY$PQBwhFNnNr6&3;mc$(8P`Ojo`{j zOYT=r3;na=w)9iGqnmA`Tvk-W9s%gBN0ae7KYYUDTGgg#b>qk-wTuecTNmDtILyg* zSIrFXw4Za!qFk5M5mV}AxynHw-{=DT|ALpv*inZ+c!q;k=EL~Bg><%fbYHa#l`#&Y zljKV6zM}8P-Fen2aQE$(DEp<}dz7|M#WcJ5KPbFx{~WF!rODOdbM9yGp=}CZaT5GFJiIibuyo0{@o_+;Jnis48>Ic@*~zsJ?jR!j%JRqf zFELkHRjs|yYXRTEl#bcF4M!RKH4yL-+frSK0VnUZP{1J5Z1fFvkwYZa!rHR zhME*6CB6noTxT|iOG_}s3zcw}`q57%_#JG7Fc#?ySxS+0sD8G*u?KxTyZ{r+9ko)f zwBBK!_6ojN44_`&eoB_`D4XU;?hjh?Fp5EwQ9m5yKiAAFwmx3vUYLuid zhTGQjCz5B>qnRh&K*-wEQ#n$m)p->b5hmy0QWmIwDz@_1Kfz5ml*2~<4**X%Ol`>kwsD{XQUo4g6Z;(PSDC>g5J+pT)+089{;oMOUkoOc^ zvj=oKnaIiHw7RsGYr%~Sx>#5WO#}^lMItouY;xFAn@NIKYf@7eB>b1_7p@KggJ8By9RUWawBtNUZVQ& zfEjS$?L#EI9(wogjeV~B;VU~EUOi!NZ*BjBoN-d=~Wt?n#J$ioY-jN++j-(hca1o+#b__aE_iL81ro>*FEIQXL{5?Jp+-nod`pZ_=Xh3Z9&10Yw;A%7w))MT~TWf zvc)zb*E$t2Ie0gUHPc~+0j;6nllv*-JmrUlDIZ#%k4$tA=(~q6z~Vn5)sza`9Ya98 z5?s68>>!=JxiqDb=CInS%mH#pwId)G{EhzHp5wN+cm6~e|G|N-q$xWi4rS@ns53ri z<^&e9;ehl5#nx6dn1#7A?MlV{776DZP0l0ZE(orBa3I|7<;y(6kr3e3CJMw|#CVb0 z8CMH{FOSG#2c478Q%c-z*7ql?JCi%y-HaCniwu;W?uwm(Z-lw)^s6gfO_|w4RnJ)G z*l`*yax(jeCH_t;ZU;OZzgxGvEu8D_*2iWw;EhAD9^ys+V)*B?$3QLvX0uleC~Xc% zypKvj9GHg8^L6&@2cmI39I~z9jXP9+`*|2`z7WcJW2=+bt$%+Fq3)bc7yaJR9t67C z3`}zGPTRM`<<7J=1+=n#5`4bQjDXoHOQO^+)ifBr9F~d?L)W4IV?r+uI}hG=P8XLm zfF256zXNl#pwNVKIbH3y+0BRhJz*LrQPJWCYmZ$Xu(lDMM|x)-dCrkq1!-;udWk1X z4{kj}KTdXZ_4RZaNA<6}_8J~>>mjykhQjj0W#o`*7duO8*4bce6K+^D0<@dq9ChG6 zqsP@GTBm!}uB_>~vSQkN7nT~wD0v$n9>`!fe7glFBkl*8Y^lllHud^;JIjKNf!8Ah zTK3SlZ`gTdU$)vsC9-CFqSWK?O8XCUt#SMrtf4$ob%cKp9WQL8ina3~XDzx}uGEI@ zUMZI_XGa~ov3I_O|8E$#57?qKhg4&w7?m8+6RaXF>aX@bTiR28fHgVyK@I=$+pT$9 zn61{rgFVi-;Fy``9cO@av`b?qlq+^k74DLAj#bn(!5PEa48Qq)(%TaD6#Gf4GfXT^ zE-fDE>{+76_onFZ!*TySm*ouTd&PF7h*t(Q29+^$_}@6boRMv1v+wO;j1ug0teIFt zqy?>haDD(TN24D7fE(@i^Y87xZ7&|;W$khFgUNIQIXv#CiqI&I4l9u((d}F9+b5fg z6)JR&88>Q_<05%1>RVg!XEYlehoYkdIGqmoJ9o_nlq(8v4p)jiD4C^^IC05&B0 zXdUt#A3=?dKztg7p7l8gq(hjeO+$bWw66gTFw^Ntz?tZ5@HDp5h379`1Mo;zNO{z> zLStwd6u|@_$Lc^aKZP&bbI^E;rz1{f{{rp7t@?PJ<@gQUI))*hHN&-5@!7mr7ZFTD z8Q&>X@a=YaTL<*kR{(Rv;+_^lIhg&>t#F9JNNJL;vr9nb0M9ZPu(|ja`rj_ z-9F4i62edr~!0)Khef17Q;}GN4yL)JyTuU_``DuD$ zdc9X9>%toKbg+4FwfyR!Yu5dJ3O8`Y7d$9s)%yGxoQV&0szCcjEq z?sQH*-`LnN&V`PKLZ?bUWRr72^Za`>`3bHkKX~7M&IYH*V;9e6_f+WD^0*_mMt}SE zI;+Ys!~Oo`RJ&X;m7OE#*^x0;#gP*8`uMdWGC2pLhv$LjiVr96XYQoOL!-x_bLaB( zn7Dj=Hh<9VQ0VE=T6$T0jxEE`;zVYhDAa8iKcL<1E`@eTkRKk<;y)6ppPc@X@}2|c2Zy^zlv!WL=p}3P ztM*GOAoTG7xIYk#eh~Bz%(%sWU`e6DvOS{?9j*cALBzDy9oufY$FtZ)d_F2%W5p59 zE;Q{#IBTIso=;f!M~|ONXU14^rK~4i?uqA=nlb)+bR>f2RN^%a4p$+#B*!^ATS4>? z^m?QU*Mg(Y6`S`x6@4G6LEw(E{FF+@S1=%`DR0buL;0Ur{7s|GVa9EL_YE37?gzU^ z+mz($;lGzGx7Nn(%vu~_7SrcwZc2M4#KX3SDnE0tj3l}O=-V2BZr^LC+|*QiqEad8 zN5`>}K4waR{vMB$QuIAhe=+LqaX>#tA4!N8Q`%z_AF}|T{rc-r=gTkF8giX21I{V7(59Ivo61-LnxeOM9D$Ld#vM{>CDu658ju`ZMg=0y|>+Uh)T>cety z1dK985~rAOPN)mz{6y|*wt^s1GJKe=%O-D<%U1>SH9}nX-Gp*$aKo+Y84rs(fC;um>8!?Q4cqL zdKCNF5}s-{xOMIK*yK*;YhL}0`W&&pn)8VD`k}?x2okXW1VKC|ffjka~!{S|po4qqN30c0{=;O0b}n0?rtLZaR&!+=Mxb#-J=aE3!+T+j3)* z!SfA{I6v4ky?x|?^jDGnNS$_KJv=QqsP{cIHDm9)3cS;XV*&*u=*)A+ZV01NoeSn2 zgzuXbRC8bU__hzBmp6hH>_VXDYyb{n!?cw6S0zT#rM$f|Tn?wlhkDApBJ+rp1KZ1A z8BMyuI*lVG z+R^Pj!WiYfBiCu2suE0>&TP*E#8Xh&nC;?4fj5*a~~Z;LY+)5 zI_Jjt47b!B)BY@we;ZeoTUE$Avv^8=!)Ue?UXOgXNN2~?EIz6{G`T1o#O)6H^yX#E zpoC=k>R56FIGeMU4AR{(tgWc}5qs~E#_6h-m%TH^Xt^Z0hqF^TSEQlyE_3YF6ME27 z790~HX}{UyQ|fU>+_Aub^@AO~350%@`5fMMGZaFdFWq;bcW!{u>2sGMBZV$+Lq1w? zH-wYHv->>Xy;KTvj-bOIy4`dBdXTuab+0ko^FeE(`hra{&o1LOjf(=q^Xc5Icvvz! z_y5WMtY5Ba4_MH&q;>krvIdWHEps?*Z@mNE1~h#Y zBLvQCgE!%TYc{3JVXg%(~86%?@_SbD`BS z%Rxu4PQG<2KRohCDqH+}1lgg|uNq#;Gwmh`4b^0z<n6s-L*oF5g&?Qn<}C z%6lHxwk8^r+noYm+MJ(;E+ak#W_oz>VBWip>5xd@2mvn=7c7#H6%*1=-JY04`r9?5 z^YxYO4Kv_2i1!3`fEGgSU?-TFRy%!gOrtnr(DeNLM?C(h%2M0(zya-U>r1M=#&AVk z;BS`$pT2hJ^Lrfuy))UpItgdoxLfX{v$?O-k)TS~A#))TiU(SxHb~HO+SixMf^RaV zK1MlVo(`aU;4--f&gFv(loxm$HXRQ5Y^%XB;E>!YXI(n)N+Eqc&7n40C;_K=%{5h8 z3@5L~2l?Q1)ob?*_Mss~=qX@}`zSgeUoynn?kd)f`tcfS&Y*dB`Z}b!wP2X2TOa%KnMblIZ`!07qg*BqjHai^OTlIK$kW)s# z!`uacECSc54*PoU5?G)DIUMi}&N61#szb%X|3IyQ_ZFXUPwj%>cyDfpc65^F5}>z}Jq*d3VVjalCdW z+b<|qGMf`<&gu4#{_1_>NOWX+Mm-{&6X;=hyB{tj`bD&(L*QKt(z<#G?0c8gWSLoY{-n4qN=Yro7^J@K7%%zAAcf2MeOmZ6?bhxy%IcWWrQ849V`8$RG} z{UHdi;0+)fW(T`jw?^i4QKJBy3bL?TcSq7(1JlUBD%{59#>OMB(+*ZXP|wcXbeG}i z6);9!_wAp)!WcK{{GfC64^L0%Yk&LtXVsQDVMu;=S8NW0LP^#g^7`b|L?s(Eg(KG* zZ)8GGN&gYEK$09{2uc*tSal?~g`d68(XM)VQt$-=7oit76eT(|`UM{MXUSUxOS*Lh zW|*BVnN*yX2*SIKY_kuQ27;hm;*T~SvM(4K6Uu|d@qrQtmy`(9B{b;=g zt%Hr7^k$%3J^RmgLs)H}794Rt4KJK9-c=0$YG<yPxoJp;xn+8qHP}5Z9f5B|zReQ2w`$FO{T@=|-~H!LKmCMF zblY!lP}k!;d3pko_V(wW?T!?8gw!C;q0SLHr#kOUngw?s%|10*@l1d#F{$zI{a2oqMSp}qt$YTdqJ1? zt>1R{m=iE@?%lp;%mC;G+I9~aAz9oEPr2Ft!=-^*`m6xDo8|0MLb(@WcdRl1x=&Vu zV1BtKC;;c}N?U^w>4GE7g>wPjmK*DjjLj3u51AeVbDgxmvQ8pKbI;s=cLNiv8qWXr z)3sF;ADRZvd#21vA51a!HOC-0lu^ z#lUH&=nqnx(86c-n|tmHNbjd~Cvpk&KC>NmJ)Lm3X8Y`QA>JX+(q?1TULxSMqNMim zS!HO`6VCWJDax3f^Zhd}-QiUN{}}gXbT8Cs20|HVM`}sBCNQNN(AX1C0*y&dv6xKV8S1i~nUXfA`b1>-Uzr zOVImz>k;dTy+(@z>91X$L#VA!2bXgMG_Jfg+W~X@&%O>U{`T^+ggO%7+!?71KU1Nl zu#3W@R$%f1)ZL7C9*+m%+?6{SKYhP*c{qpPrjggd7l^VmD3y@${J83n9Ih^1reSGYF==Xq}Ryn;M%%JT`tQLWKUA+Jxn zJm1)i%Ify8^T@80*vf2&C`V~G%IcM+ZpV6dK=j6?<}WueSNbpi{gVM5QoGy5*~1xn z;Fae9mbYwj2z0dh-ZuO8X@%3!;+S*$#-v@Eo#q4w=(7Ybl`qW zR>>&(KxLrHqV6@u;j_pNJ)RyJMh|W7@p4AeeOn>5y}!ELZLvJ_BKSB@Le~lEzOgtV zQm`z}(fk~iXEHcX~D;Nw=m}}{aJ~H%VPzgI|u-H@g9JQA|j%5 zRO%+g33jqMo}=ovOLGJH6Ze?Pd$!b7%=^aF%*=lo*saa~_TNAK^vh4zcqVOpbLbA4 zSE?ms+MKP*E_Rn0>E20>zKmn2F#&eS;xAT8 zJq9k|)J#6MVvwwW@SH7^a1Q&8#GVcOVtPzrHM{0+XNpC9tDxu7NO8Hz$2?m*C&hW~ zS10@i^4UMB4$@Oki^Q#n(vQ${%H++)iar4+T|SyrCo%_r>eG6T-(I|#iX z&E3_W=RSq1W}_QKmqf<*&3b!x9aAX(^0#-!=-_jE$p{^E&fIq7wZF9%XOo|b&$ri5 zW&nOSc-Wim&W)+IH8$&97|yq5Y3w9%UC4RYG-~8?U-bu1kHi0T*F-S2g5>{8D4ilc z(%oI57vk%Q$=L?Z?h0+>toKB}1tKVT;S!hw<@6cdO~gLpNpQ=au_{0NoyeJ0z$pM- zP_Tfxopp8fFf!YHVtZq7J9!!8ZCkFlenjSjG|MbNNF4il%2!JtMrZrYhbt)?JxLRE^z0 z(0F#g^;z&Zhvt-8-Y?*?R_74uml&9DH=|^7^!RGoy zpX6L6;bO=+ljcpWnGH8FIobJgX$e|-gQ@HrT%c$himM}_hWidUnelD~$1yjWhKw85 z?{)88H>kh+$w+wS-T8n2=Q}gv4CwsOL$d*1nF)uk{a5&1e>TJY4Fvk$<4tOF*nn4o zYwIhn-;B?9JJmU#-Q_>~GFa;fOw7x`Z(bJw}tb6Yb z=z}#cCl|S6UZovV;9B#nDe;ZfSJA2)8=Te@WNttYGIwrQ)LRms?(%B}_49X2_dA_; z=YKnY_tRJRRw3QN=TDxXuo%a#ynf?^{sx4;uT;1t>&83pCMJw%E;X;;XqHhxzGA09 z8+^`6afM@%bat?~3-x#k4337^dlA|NoHIctoOz;cC-1aRL8jkT4rm}e zp&k~lrb;v$j{3X+^c}RaEO^8Dp2>4Sd|!dE-5uxiaMdBN=DY1{Uv2;We6_oB@BHt7 zL#wYMSoQ!)0A(Wqb3^&BZ*hgk-5TAvVsppN7_;6Mt<9N$JM$m^F;hm9v%HO`39&y* z_;e#CrwY5i34KnCFZw`La=NFth33{&=zVB+9qt6Km>P$q_Zj*H%Pg_`ZB#6o4~N|B z95toua%NF`f;Q(+OObO|;L16dK9??)9-q6jpki;xl1Gd-#+EaOy%5Q*_eFSbN9-BX zudDXCPrsg`>6rN#gU;cU0rN8C4Mo1O_Go8ga~BJf=5|vVH!e1Jp{k+Rq2f_C?i*M2 z+vl&&zxr-<_5APubN=`9AHVu;8WSGdne${{HQmpCJ3D>zE4p{a&yP>`pBw<@T}-h4 z&R}khe&d%LGdC*;gJa-iHKp;lVxG7>Te-w}dN5qF&il~NpvI$nWp_@Du9!H5denO> z4opX-xKQRvsppkQgim7pN^vdazR%4)3}3s_C36NVW7&$A`}mbe@kmcmSV4X}d+)-W zq`oY2I^jI7JL(RqRy??y?~1&BM_4V8i^kmH5->M#Z|UdKfXHO{%-rL^S{6P`?;-s$4@kU4xDS2z2A({-vjCB+K=~%b5rM2 zGwti!&ClAE^39oF{$r+HE>)_F)y2h9FIg{F>gm6xRHG4rSoZo|AE{?OW?7Xdu+ZT8 zq~QxOGJ5apMZ3K~<___cdX&_H@j)Y#$32>2rUWge7 zKj%a^Fh-*%2R(L__ulKM8S`l^C*4Kpo#WVDv*vjEixP~b_SBR$`L#7AvKy^qyg7;d zkq6Bm$B;f_zI_cUKTbBUziUpwS^pou7@?bO*(0axSa_Jb$mvKx(6sRpHg{jgGAdvV z7{~{kCSG zO4UqJb5Dy245pB|i*kRrr&^lv9mauePr-6eyorAuVMJnuC=qZIg!4%8CJXxRFx_JgyWLWU!NQzXXceP`T6;e26>w8 zPeA9-*|l5Ge)a}8;QT2Bx)}x2s4Q{)9rU<0`Y*rSXt!UyAf3M$&o~d0g}#T#l^H=f ziEy+t)0GES7+0n{{O%l%uFkV)hP%<-hxK6e=t=wb?^6zi%($?hZnexDOImQe9zkwT z%T^M*k1fyR%_C_&i9Zzxj{)pLrhc?OyUc<0oF)Czrvr$j;}84G3ZwT6^cF|&DukXh-Cd@qfO?kab2*M)Sko$P z<`lDKahRL}m#pY)MyHrLPi^3t=MYLoL-y6ehZiV!k5Zt!2=5rE=6y=C77Aa+kzS_M zm>Ja(&e5ksoUhT}y1Bz8uF($*FX)7h)<4}j}eN8cj>_M1bv@yO=1 z-|YV34X?OCp6@^2+;F8a=y&kQGxDcdE)~!){CrO0DBVT{aDYGj*qKjfFZ^y$~hj{ zm$U8GCkP^Jm{e?yrCG1;)LZaT`U|kR=#<6$=Hpe_1dk1|8HpB_Da_IPvC1p3v^E89Jc5|W$M)!X5O7^+WW}E})wA|f% z&qrGWbY!@DIi574B}9IL`$yR_*#)AVg4eJwy=OOMdjLsJ; zO$=zby40mWmpI=boj+nqJH$Eq_WeCfqqhHKA5&^zxqqb07X$Efe>gcZtiQ5dzeoKr zh1n0kh1>PylwG^`>~B7(&7WD5?{Drt_`*8(pSD-;tuA%%t-f2m-kF@7Lfx`TWeZh) zm3x3gQlD-0{YN`sLo8-L6s7o(-8PDfdYXI9Q~BdKEzi7FaDg4~y|&XWZlW5FZH=Kihu67IA>~gsqp&uB?@gOIh^SL#=Pr!3_nx;-vtDhO#pK}}KsB>E+*?$lsjW!kYZ(nYH;de8U3-=FT}>?cVht->u&3FnHcxEG<7&dQqK7f4Dr` zDj42d9+>dZh01Jz(5oQyfVmf!p{uUYS3pl?M(;P>RiCOz?0qP|$msd$9MrOpCIiD1 zvdo9+_x8-RG*Zor$B4~INR|AQY0Al*a+1~BAzHJ7jfu`bN}p@a)60XWv?rvv=RHHvj7UtJQ0m*UKK6=5CGt*`o5{AjaM6E~TDb z?!87SAHbZKz{9HwupF8f1$RCUoqt5?V)ee<_K@eH#*0MG(df5k=e5mF0iJY8dMmU$ z;uYTrbB;3?!Fv9=<5)I3iVSis2ax@Q^@jqT_wzX-22!OSx*L57!O{y%xJ{vgQHZ5> z*F&EJ<7jnq`XfF(a?>23)tx98MaPm7?2PFz>=BIG?PhRxn4g_E&H-}k+1a^2drY9O ztgM{VKYwlY$9G>{GuRX9l^!}RV%%UYtmke_|IrPW$SMq1oG5*u;?V{r!=pw==J5i| zkxY95>*1X57wGc070vZou{#}fCfmkiQm_$}W{z6vDZd;E=OY?>K4$pS6z7;aZP`QR zf4=hrC83xS?u=8%=h>elROiW(!-ygU{|-0jqVQ5m4wZaB9_ zcX__Cwnlvpb-t;Kt?o;oA8W4jeNJr-HR|0(XQ2WQ)oK(qU^ zxZ<+8{|pLYdVTu|=T~1@`4NxEcAxAtCq^0+=lW|tW1Nd@RlWD)i>cv!z`1e}aBMje z-Amv5YazftihbuOI`iCJmnWIdmy2?I{$dm!G$nrC2waLyTa9$jr1~=Rz z8tv5SfVQ>xvu6M}pbNJen)%Ipwzn3})u*)PvE$RA^3$_p;`fC+9n@zuft=U4zjJ@?3Rf z6k!jdPed*<>b*=UVjRci#Zo-~TWYn+HZQT1%oOupgU;91N$8twb+-GXUAWqg0dl*e zXQulcZu4K?ytV7EZ@75-=J=G?GuQ3UPsQcV;~z4cfB2`6ZdM#9eRBgv;pTZQlS^z>`DI;7+&b25S=2nTXcoXM?Q|J8v0)|L)* zA^jL=W^Zt;=6+MSvB^Q@AFN-0re=S<`FPV4@rZLzo1dBlc8fMkp+-z3BfwBef3y%& zPwB51&k|&Rft-V#KOUo+-0o@YdD=H8DWo79^=dFl-(%p z=FUS|ME>E_oZaz0_Jg&m#m>*1<9N)xeEJ%*B7Ko&CRCaYy z(R1cZD1N>XS?!x}y5{8}0_dFQ+?w8X83N(DzPEM<((PvV;}7V@4eQTOamBuP3P$H6 z8T~0+{-4jD{ZmbjFXB-3Z??a~JZl@MQTKUg@vNfv$>g^pzCi-52uJLxYbuQY_s^t{2|IbO=oBB8flm2@=}k1JVj-USgFH zmQ20&ToAbJ=w;V=wD4!UlFzXy@_GKi}*XoPP zMA_u|1Ys_Rd*IyNa7dR?fQ=PdJDNsRd0`mO%0{&}X0rt^2X{G-`(lnGXFR=)Gp#UbE+!la(W->{ zlqCk~S}OI(=e?JI%>+-;-dlW89{kLDcGYZ0R&p*MLnO9-UUmY7ck^^f8ECYS6RSz0R0IwK*;Q zqEM6)U&!D$~fD zROd?~bmMc4I!DypbowKVY50bnJEG*rCr_!&*^n^c-W$x{|HH2De>1e(1Ml|a%|DNi z-y9#?UT=;i-ua&6H(8t8-4y%>tvuU&`gn(VS1|yd!`iR57nhfB#h`#W9W+h#o(@P1 zLXUd+{ztQ8#6##V&~>ni;qduLRxl{0$<|apZfo3k_v&yTwN;;Fzcmg+KcADSYHNyj z7icQwq)iMD zo*>QcFh)Np89BcLcxt^3o$A-le%`xD{N?Il(=>Uq%53wIf|FggA=E z*gY{`tx@W^I!9({8*Ps8`BbO#`81C4deZ2RcGou6*TCn@j$;JOQP2*Mzw1 zgD8v^`VuD7K$pVF!+BVp%Tu^GDN>%QiJWq#yN^}HIqfHVaY$}#Df7RvHwNFHb&R&ZX0&J{&}(W_eDjuI179N>?sQJ11%p?v>{I%Gh$$mo6&A29EPJf!gGuN{yVyOAsx7mb@T|oy?K88A)_3Penx|yYW_Kr zY#s;B1@ul6!GiePMW7c6ol{Ku$e_p)pg{L-4ygj=!OM|TT$hdDUbG98{0A<%+^O^r zME&TU*4f_jm~UwE^J!(otxS6v84X3-jT|{vk~x;6{euf}vbi;}UHH*|22z}*WJ;^-}XuD7p?t)E#2wSV3>OB7{pBW_T`U>Bg2M3Pe{j@Rp9)BK3C=H=>3$UfQ}56;S$OV#yc!}CIzu7F6B-D zy}lU<`C!Bt|0QCf%3QiN{w#oQt6?~-@buu zZ|2^6(DtYnshvN%KZ;ur9*{sh~J$I(^ zBXFK2I=t{G5yw(^NOMnb|3k5zW8%`~;ZjKn3Mv%zM>1U-TXXdS=|HVV%q(#=Q(6Pz znZaXCFXz$aMTlo3UT6+Y?v6NMpF=!izzQa0@MP~&W%0%TeZi4xEG2_rHReYZp(D@z z0qu9ymLp^W~v;EC`vAG#)AoFjJ5}UIlFq%hj9YE&@ zHVu@4qkny6>cx1yzmuC~P4`wFe80S$bB0qELKZBAEMr9J!e99jbRFgFRM=P<@PD*# z5$G}YZLSzx4MGp;t=Y0UC_Qb;6rSjw#(k3DMQQ3B6Jy|di!VxleNjT0q_Np?`Sz=F zveRH68hTM?S###$y}+;_4DfDCn;X!Vx?kWz4u8PeQP$Q)><`etZz9KiAMtZGJ87CM zO-7F<&#g{74z$il4CvjEZq`1?oOf$-dgOnjabV}h*(tdm`SWz|OQUaeCo8>}Pz6i^*K1@=)dlQvmbv)W>hZ zAL}zLjG*pQg7lv?P5MF-=dF3S-E$uxl*hm|pRgd!Pg1a9adN*Hs2E3UTCo%$7tp=t zBl18ir5cm`IU4LUkD?Oh(^rLZ)`-FCnjr2l-#JhkoO|Igz?1%3!#d2GkS!hCVJ2&z+B`ndEc zZ59dfJ!`@j26PRzW>vJ&(5OiE9_p1ixLftwIqdv1z?@U!e$L5vreVZc3$IMa+-eWj z9#Ew-xV=ev4nl{PMw|Z%%Z%du?e7`p(dzFd$*I2o!O{{4o)-hC_!v{`p7s778C7;l zJlQ|^hFS3(Q>KsUCm`r|lqC5lrUzyNloLQ4I1b2Fd0q0M7XFeQ5@l31}%%hZLhf^{7``?YG zDarrUcL|XWYaEVwsB=`7fX0VY{i$N{$e2t1dt>(JUIEsaODkdC4yf%DOqUTC3IxygA^1@oJg&q(K; zFQLs@Oa^%=4>ZrxG*P}zoD=9sd=)$e^+dyfaM3hd{q5c4D&ct_pN-U33 z0gBV#PT37$KssXR7%cO|WcqgZYDGr$SpA|KE{7FexTK8W4Er>2D6->3=!&~PY!$uk z#X&7#aSDTCHe6w}`5zea+BD|_ru%BQxd^|*n0Vg{@yeWff|ymi)kqO@Rf$Vw=b+nB zjR;zlgSAz8$IF&CdQ52dwE8Lpx=GYUYjxXqqC9~(s?@pUxm~_^;Pu|{Y$f!$DfEra z{b&1(pIduBKRZ4q1)ou^y?+Zq{;z)(p$m@9u`ZO*aj zr_Wgye*3#`7_5J?2a$fQQ&ti6B&<1$oRZKzXCSBSvx0k+bC2Qa?vv24f<|L``IdFW zdjBoXU#>-=G5pn}&O@HlWAeX5(HVH}KMnGn*%{9l_@oH*mi)5@_ks@BR7>hQ3R4QQ zq;bXC5}LbIE)ApYt<8}Q#YmbK#CZ)_k7mwQCMG7J&8IpP=3h9O1K*-^qjkqQ@+XuI zw|`_fe;$MmI}SL1|NHxJ!{xsHt$W)URyz}&qe|3c)+wM0k9rjmtUEb9d4g(_8=Pz% zV_`7U%QXUn4H#Y2@dwqX@VS>T7prT^^uio%tndD^RAOBQaXQi7Tdq5$ zsh*07^fu-cFAp-md4jcD=xo2*rLWz?=SJmZ^cAuBS`MD?n?6TEoa^diyDK9OW?Vm^ zgU^xc4w8Oz_8aLO<=Xf5Hurr1`<^n|A;mFGiK`Pu{Mq;v84I(=~%(x7TGuBm}_j!`g^{2xe^=+oz6xEs(5wEr4( zZs10St5EL6=Qyhmr(;z0SEb01&apULS!uo)@6QSHJVR)b6i1BmP+k!~F*-{^E~2O7 z-2e=-UIETA=`}MYCMGBTO|xK_{Wksi z=b_I%gzhnPB$^|9j>2&JPmcEy;yyk(KHg^%vy1OHzq(v2&^hEdqUDOaa-_@KQzSH7 zn|qbHjkWD{3|!egIMjS?=SP}r4fW(e>`(UXcCbD@^`eKg{eoEbspM2*ow@#z%3 z_B6zLo*sSh(twZm?-fRr7bLba)xAYDa-c8&o#pw8`xn%@EB&O}fO5xgzis}}DbxRQ zl!)~i)?zZXoF5C_FJqOiHTCRZbXH=C9Jrd-j=_oErjNb-Z|%wEzoCXVYJS2AH+>a$ zn_}n2po&kl`*pUNB>F5oSfyhrf^B zeGayCVdcm91@gEiHOKlq@ALj4^EtMfIl8b$UwiiAW+!`}-@SEbIWp-e%`cQl!-OxA zq>I7iu*=b*!}+wh{GwEqS_k7_YNF<&HM-sYy*;U6=k94=2^QxPWbW~ESa6#Rp3~pX z40k!*A-+E_$JumxQt7{w&XFvq@#xO^Q0Lavo5AQT7t1tuGZ;A03nzG4kBV{}=We@w zv(ovjHyf#ip5&i-JFTG{{fMFssf3PV=#e-uc&U67>z7$2&H#KRr@4pR{v$?bncfiM zna5crKfN!l;OtPSeSzhl7Q9#2$^tww3w-U)9i1-Rs)e@OE-+F?c~Ke^{E*(|vUAu-b8B20OFZ*ESB~vc17MnSuOg*vT6GyOmD!CI97e-H#}qVIV!` zMncsPEUd{5+E~$ePt+i=b^H6)u`j|eVfM`8;G#Y7t^QFwjJN&Z6U+cB46=;x*-<>d z4U>#7mAN9tUzEf?R7i+cQXQ2Fm~47M;n?(h??C>;9>$(D|CtIba@{?uPY8 zdkmfLqjju zF=TY#1;%v;*m3gd{2#?xZD+F(ZW`QH4ca)R0dhW~CxH1jiH7D9m#)DaQjI7lymhw) zA^2!x^D)Z38shdL&YwPgc4Uj^ybI^Q1(e_aTF8z>7YwQ0U`#$9gFBRxOdsL!U3I{F{bg!zY2X7(`XN$a}=i z)p_^YG&mgvU+HhBLXRwWPNhP1&fvKO`qQHi&reS|s+i7qL%b<7=DB-5-0vvodiq># zPI>6!fRZybKIM}BaA1UFFD8wZqfPlx+lD% zs55GV+3o3b!#Hk)I~e@~u5imC=EA)8_iFUF|41;mM*j!Avj+4xZ;Yh*N$j-`(USn@ zhHHa3rvBMhbjP0C%bJw+aAT$0B+l8T34=<3b4a6?C&aC<%NzNGi;)WYy#ZU6GR&C; z6F?VA*(1{=kEiK%y+j@tqZc3_D{5;MTXzB1A2%0wdm2<>oOuM#mHK|?j)%@Q)A?8q zAV2gv?TrRw$(REiq12j($14>^(kqw+oHK#fhDwy@rpUX~lm8zu&JjzKm>bQb=aT2> z*df)F)xNn)H4ULGZGLq0?8DLViLD=>FpiG9%k=lmh+*g)tBj35KYb4Q&hR-4wjWc9 zpPZN+XXSTz-PU){G4y=HXIg_~X8;|fjyc?>s%f%#A2Sf*o5T1y=GVubd+^*72tu{< z7$l+2T}FE@!22t*7c`ck z&297`RE}m~`(5 zY|fe1rq_jYoNF-e4g4M8T)iFsGBC=2d^f{-WT;v#JadG{11)#-eZ0%$&%K7I8fE@W zBssw6S%WP}wmdi=b*WNqDDhfbF`_rmSYt4Lpa z_U$vLbFO`$=baB6S)PX|zGcGtbK4iJ|0~nrt;2tdInT{}_d4#@cRxKp!sO}ayGMrx zd(Q8oIa@W$x?<_;Uv%hj&!fkS>O57t8z~LvQF$ug6TGf@VHYc`mhU@p)Ieb#*6cGc zCe!yv&x__3q}%)jr~7<#^+|cpCHNME`uJ??&IK}etUIPUhPh-gU_cQ*du4w+mV$1cHfQm z=K}b%r=)eReqdFJ4-Rx-{jGF4ungP&*I(Zwe+s=jI2}o|Tv+$6QqhM8Mi}P?bdzqJ zQgMBolWr5}d*1=))h+l>mdEHIA;ROhm=H(zZ5Xe>?T8-H*_~*{LROp|m&?eEbDn31 zp>DKbvwP>6SNfnn-zv6M!HjR^kC+QB-YR6QCux^o%GvA}0_Z;4+LY-~Bb7oweFW!C%aSKDWH8xm+2)E`4=loQO11} z<>5k`qXZcnc{3xSoh#%uep- z{2RafzMuD9Yi)G)$J%SJz1S$vy5IY`pXYg>H<(hMoia&1Vka-m1^I|cbC-mWb->n@ z!O&Ys18~dyhvpVWe`qnN+h`1zvxR!-#*^FKrD#{G(YYfp@2i8+4c|oigLK----UI} zbye`(m-EiYeFegJK{^ z3)o~4C|^!GpU+NgRfWv2k<(Qa7h&_bIy$l_$_mrn)^+aOXfwzoH$~x-Jw7x)z`3j2 zwkX%O%_;RQwk&dwfgSE#NB3hL?M)Vaud$?hldFeoTwOQcHDxZ$f!t$UCEez=D+I;0iocWh1K=D!F>o#yPADhL zrO_9#^pzm5bV0a=CgHrbt;2BbJoXJ8ZNj?ab$i*>L+{-|-J!e_T5AK{b^)Cx2h@pm z13ve9dx-XKE|Ew2YIgFj0aQ%_SgAQ0#2W>kma2tDUyPjcQ3ATGVc@0VD5eU3DzWVnPmg(=j!bZN!6=05msO*H>Op?otabUrxm zd^wjRwt~2-!i9KLR#p1kxu%@Q+c4~^7~P~bdw=3-1?n5w3!rIH=jmx7ZdPLGs|gm z^@a0|+9Un)gW~p}Sw4q%{{)a3RjQo?u2m=L9&HPs4!5Jkkt;{lN;Yn>WAk{)J%5 zIt=ai6-cZZ$_pIW14<{*o7em|20)oLH{KS=32`#DN4Z#?4Prc>@3M9?bo4k45xZNS zp~tR-+qP}q?mu!P{T5Ar>+9nfPeQM2CY=XB=c38b8F`zQ=|Aqg7xzaHN}Vf1_uccn z_QSu1?O6m)&b^@S#))j}rtF;VrQvR>!!F_OAZy+wj{po!PH)CyeVcv8m&{L}X!|psmvRs9M8Jf{BU4OG^zkJO; zS7jhX&1_q`>USVwngYIG;J)uI|X?O+J56D96B_r)tN-g^a7!RsDB5 z?PPRXd^trsk-mU~`+W=V_gOWmbNSwyb<*k4&iRFK>)JxJ@7f?b=Kyb9uCQHeTztOe z86)&p{wLHT+?8Sai zbRsG4h##&q(bfE=Ej)M7KqbyR0)LOJIjg2>~o zwyGL!E^Yp-Aw8JDx`)PRKo)wv4`aM+4s$ognzi;S!T#TX`@ZMlMKiUm2AiUu1JjGyRRbFqg)#_D0gHDyLXmDiU&6m+se6>@Jzq1l z+N_A(4)b+!88E67ojG%v5?AVEi9Tnv-Ff3HQ;6E*T-Szidn8hqa;B1KynZFg4buR1 zkXLhrj?)y1BG%odJj>j6(0SfHiwc-eBVEI5Z(ZLAn2XEdu9MgcMC%I{SiMZ)d=2dk zxEs(7;cn}Z?cX|=K9K3`_{K}Y>-yxzp3R$ybByW^+>zThWAwgWXtzEBy}8lMZEHDl zg>`uC3+7IhqMn!KaL!(cj=NztzEil3UX7=B4}C9Z6o(5`O|e_B!jkAjc7(_$1>qdX zgA-Da?viY|!RwNxe&~;eX{`rJ?ve;0q-4;enh!qtJjYBdh4W-?Z+vQAKrf%;dYy*- z;nSwg;3NjEdHh|jC|_8(W)1aE9qnyg4ppu_P`QQO7c697nFTeCbv!o|=N4smjE;?O z2;)Bxse9sgS#mXehhHu=j=??E-oQBy(4*_sMue`4xb;DcIxfRrx4K~Nlwz$VC#NQC zX6xeb<#Qs3RQl(t*h8W25)PWNR$L*OUhbOUXN2NBLg_)1xJbBt5`(82HE0YJ`r!`+ zVq6kCifb#U3WB$;)`}Gvix+2z#iTb~+dr6>Fqe1XB5@X=nwbGg=YmsH*h6QQYQO;U zsTFhQ0?SOAu6}qSQ)Teml~2PkzCZ!F`w9&4rqb^#q*#;V?qE(x!~YJDEgaiBrrJEk z`yd@tSi5=wkD2&Xs$1+jI67j(gu0Er$+;4z0#? z`a$x zYJrN184O;OTXNkk#%7fW(GGlfybEU_s3vu(CJ_e)GbVOQeeq>5_mKa-B$z zdhFq#z&z0`U6p}epE+GUV}q;H#o;m-fgp`@Sx(wK4KV-qj0!q$B<;f0jBqtmp1X{i zU`>=4Sj^q2bdkEw^*|4N_D<8|^xAEQbiQF%TNr%jxE^OROaXJQ)Pupj?-@>Ab@5l5 z@nD0yl)6w(lQR@2Iv3In=D_)V#CZsBxi|rxM|T*46MwtFdcf(5RqziI`G6yW^W0f{ z!!!*0fpp|4rj+q2Hd0vAr4!9Ao=xTkE6=HfP87!UBqNqjLq^ z9iyw7y@4 zoVT+uPNrU1V-3sjTJYV9Wt#%Z4oTc+B4(x8lyXAo;7IN;d)A@7fy90EV6mp6#NI*&R9ERFQs|GeGkCO-vQ1UYj18`Sm+byRmS7_ z2K0g|4}E#~vBm)AA!i%bRWW17LciTUAj%mfZ(h@`C9nzfK^4V{(p^NxZ79%{ZGqK^ z^Ef>?De{Fis*+-3!ovKyQ`u+>f-!sdA%m<;$6L3>R0M zt+Y#kZ;y45I^RuJ=`Q9TWJ)3&9)Y@a+Y*bUFQI^2N^!>|IHjDWX!N_F08S(;&@qD zH8-!KSWbG@oZ|A?dZk3COp^%5U#MIwt#Cpji-n4(WHGE>uBV+ci^}|4)9^=u@uA)+ zrd)mOqFFgN=K#9<1}l^?w;cv2%y}{}4xj_%_bj?+(evN^ZovvJIXjm)2U9k#DJ)q29pm$= zO0l_TbfMl}sN|d1c;7p8$(cSSnLGX#orl3W*3F5_EsVygM;%F8y>~zpUHUB6zRez- z(uOTQAkGR%_hNgD!cV;f^>izeB2r=35$JffN-Ot+enL zjdR`?mqn6084R$wfDye*z17(6L%pt5V0w8rM)p~m;_+!|c<$Z%;J!!x$MgGt{M1uV zZh!L02fn*~`=gEP8@Xy3$elQcqi!%aoExQA=~WTC=H>wBBJc>Fy_+7gximX*-q6zI zg5{QzV|h(7X~{F#mvA50X0`{$twN4fGs5}$_PRzbtX5+<=U)EYiYZ})-LZI(Srh*4 zFEo9f2f9bP)yjmmub$B@v8M6D*59>xXB?daPOlB;8ycg_X0{2rJhJCtAE|8*1ozUV z8Js;HonyY#_iy>md|hR zy=UL^`*DNGpL+bMA3p_~#;8U=(qfj)Omy4T^swUp|c2Z#;Mb2T#VTGmzU z@XWvxa4w)bI_J=iDK{AM6rw@y+?TPN zJl6o>>fbXmahtXm_o-{A?Y)N<-?wl7PhL29@X*e~FYMg8^T2__ho5-*3EZ|n_2eTf z<~{%u7ZsYrUPuzh6QXUo^?r3J^u{Jf>25)DQ{rBrw;8Di(wrS)n$#MW>!Z0Dri;v5#=2arF%|Hy#@hYlS&eCRM9 zF!|x1!t5~r_NVrP-*GFf#yD>uWHYuV!3GP{&nyA3>?V1_iptIjd%6 zM$MdUXL8oR;CK)4foq zKCgk}UPp~>lTzKhLT)L{^>iCA&f6NAG!vzXPq=XL_72zaD-qY7kA7|vNf_O2`0VKD z?uoa@q0Zs6*Hjm-D6CRj@r6}|`S~-Z6oVkOI3$EQQ{SqMkho^ezgOyWOo>Cm+c|24 zDWIp#7R_f(nUcjO?lY#QaerQMCWAb=>{Cp`FEX&bjSn=#a4 zp7~EaQb}(`Ob595qAf41GfjfM|s45C(Ij|?sh+C z1?q8_y#t#TJ)5}O&!_BePq)EQuzAhuBH~;H_k67?SoAH$|hsl4omsW?__mRtw?ElGu14j?h zZ$Edt$yHv0%p-|eKogb5fup?V%g&6YS2phwkI|X zZjsY4JjZ4NAOp*MGbP9NKk;}g?kz1X+~UcHp4=qd4WDuhXpO~U)M?e#)fjrJajz<@ zF34XrWi~Z5(`vlUb~oA=CG!^5Xeo;r1m_Y`y%T)B~#@2xz=YFy~lbxX`zCaX@eIWbTn3K-~x4Tgm2@3u6S&;oM$q z8*A4+zBS&lHBQhcT02_eyc79dF|c_NObsm|LKn{S=d!OCM?H&8gwZwUwb#n^DQ5PZ zr0urug@nyCqr7)z*OX4@2HpW5E`@H+x)N-qi*q7)chnwGdg>^BC$TRHv*Sx$gKw*A z_sQ32lQPv!t5jWra2Z$cPFK=6EX201Xr|Vgaz73~K64gL4vWLk`<}lCcE`&jM~)mk zaPS{a51%-5>ddKAZiA<6J`B(9fQ)`%`;$*S{(y7eDbQK$u8!`7l?!VcZGO1r(5b%J zdZ3ebZWGX3Qj~gYdqXq(1u*HYaL)SncCBa51Ae23$O_q-AzR=W;{KOt^22Ev00o7 z-P3qXZS4IdbhjG1UgS?gT&I7pGY+jjvWILq-qEUIX_$690rg_Xy{%dG;xUK6%Ivth&_S7nj+Xzqria zax1dnb8%U~7IQF^vlyo~eL9VvtqJycqUkNoV2O#XMOH2v)JT0|2()DU}E(|qqSx6J9hB1 zoA^pn$9@L84D!!!+X!LXYmT#ydP0`wnw2zJ*#7##8+&nvjSTaV!pM|FdI<9n=cdgW zZgbwc_*|(Z*K5H%cermag3Jl=|9RwyY`z~rH)Vd{=;@QgXMphY=g+@lj|*qd6X~G% zlN{qA-(Fz6298{{M|Zww^ePPQ-UBD43+fG)I&09_F8AHJ?R?YJq?A~f)u*#*1hK0_ z+~Di@sBsxH1=Ja7)k(rVQ4ZIwfWwXfeMP~dys4hIjn8Sr*)xS+h0zS?I$8mfZ<0?= z@7y0E()mKg&IMVDrHv0s~^ zxGKnN9{!QpmfQs;*?*25XXVVyF&&waZvNZzKRfah+@C+fF`b6T$bRt9(L=vD0hGT2 zYuoMOxmWoDsGq@D51SuWz~%)SeMO;kIX7InK~CJlI*Dy*bc%Gz@&DDLmzE6;PMte> z-qzVbU0x_cZ>r;jl&-EW9pM*Ic31L&YpJG+4?OjOZR&YKQBe{99S<;QP*qq|R9#q* z_u#kiKezuj{x~MKEiW#WPEbgNZ>q@4%gfJORI#aoIF@yRdW!U{VvY3a_M*FeLoJ!Q z)G2c>v?ojS#o1QbAax#|Wbu*ky%*>al;6d{TO#!pTu)Z@BBxv#ai+=DS;6ac=eTFH z!+?DI-0T-^WXDjh8(snQBQQAz_S1(Bojh^sH6k3Qe)astix)4Py?BxD$?ha}j_-#K z)97H)6@^i(7giN0`Wj=4@Ofr&IqoLhD=PA90NOq8ElR_hI9_=KsiBv;=~!EdISI;xi~U}CYRI=x)BrkEH0<55!J52m;4a@qan2?YmYP{Z7mWrd z^nme7L%HPteFb^>R(I>R`S$yOQ?vI2l<17LR~5{M&8MUXF*m2sIZV?dFK4&My!q8# zI~2?tN?g7?l-SW#U641op!)Ip9b4o5ymv8CllP#*`IOo61uR!-;@le`0^>U>WfZ3? z)m%i&p#>)|Res#M45%OMI+Ks4rbD%E`aD&gTf$uDQ;K5nnaK2>+%eU zv^g&tnG@tMy>##&Xzm014-(`@PXpwq&b;>8Yv*6R2z!rQyoATt*x049kuki(F^u*E z`^n)G@aK-f=nt$`-uyl$(b;qYBQKZBEG$}GQ&?FA;;yP8a~G}VSL(~H8R6WZEg@S{QYNm*uggPm^L;UE?H!K1jJK5Z_$jqJ4fDDK>h>Bb`< zc!2#3$M;hX=?Z>@F*$nJ*1a7lSH}rKoA(yo`5MB!tzk`Fp*iDp(+P5*7q}(X_0&dK zpFj5p_s*aD{rTTv!OnM_$qVv@^A&y;JUqC$b7xShnQN|TX$+Bjr+s!s-u(KSct>(* z_rR4sd#=6l=9{ly?%&Z>Uju{>;ovg^R|a7A#Ew`akS@_K70-b}F*xSb0+dH#9%%E_ zfP2amgw!{LcrAUhT&YKrPCx?Tj;9H6mE#fU@nse~2H}Xj_36BM^Nh|hqNnrSykBOd zznGEvGmY#3`AY}?@!-*akij9#jmyuTfGEHCD(;tb8@sMM9(ZHa4y2zvbMg#<{>1j} z4^$UbN)t;UV_$?0mTqcqXl}9FhL)C2ZOQ8m8@xPcU3-JExry&0@OZWOyQmtnn-A>p zp%_5^{JeYdz@3}<80~Ri0i)+v8I^0h2yD#e0N``^ITGk%W!uZEs*lAJ$st($&9~lo zQEU(s8R7qVQl6EMwJ*Crai+o<1yEtOJ z=x)kB{cv**@9wv2N~#uY)sCxREh%xyBd^X0YX@_ObGY{}X1w_K^4VW{>A*h{+(P)# zqc0o+$WM~W>9N0R7$?9-@Vvq2CA}fBpFe-*R~Qe@oHC;qE}*aM9BY-hd!Q5PU~iB* zwxsbELf$-gi??^QuBlsNUO4I8Fin&f6#{o#@qE0#9uGO!0CnE{yt(u9zH{%rd0Ywz zR_7v~D+;O$eNW073tH6&W0{QXyV-Pc zHs?&wrVMoQEh^MQ2}ogXDp7UYN)*qU$61N24&mY(*0|l?7qhgNCeM6vpG^J|v3>M3 z<=Ii(PaisY^5mH_XC=u&-4{kKfyYP3#&y5J=k>919KmO=ymE%OQ)cwl6wlR_N~m+U zvc?2D6gnR*4Q^;};GPEhK%%#?M<*b@urXFw16^Lts1EctM)YdfyK5`N`c}L=USGq5 z`T6(dLrv%1yXoG0H$hl0!n;KTdcIGc!_zOI2UlF|v*YUbry1nhtC(6<*wqwI3|-wr zd%wA7&lL>g@kG2mp2V>|*WP^Nt!r;wyS8V~)uBXxS5c81`eOd|OrpDphfAJobayh` zDR%dXe+h#vDMoZcJuq;se6lEIEG`QRqq8SpM{as~w!^uHx#iY;-c8ja^U^bqzxX0x z{y#zH@Y7G*?dQYHpZuIKCzk`}^x4P8#N#){BO6`@m%!<-ocYzS8LT_?^5G|Tu3lYO z=uqw|;yljf!?hTddrEI`F!u>JA8Z$!<7=u58C8P=UB5MQ!v$baCxI`5(Z97RZ!S=t zr=|$`)gu2wx)ut;O)=iJ@)$LGn^9q*wg>a8yD*AhzWVx`xb1lz)Sc*6qON1;Dxm-7 zHNkuj#`eUHtueTSc~i?3iF1?IOb(RhNL7X4W?D_pkkjv?#wSDGs+MSZknt}weq($d z$T(jr8-&>Ha|w3x`MTOU0b7*qTMhDVK=YaV?9&`pjJ?w6T zE({JPzxe9dMWb>)ZsLvy_H+o&{H<4BJ5S<2C8KW#z9gqBMZ^{(r$8r@!{#)#ZB40p zf!>+mWK{Awg*l#3M{vINEUJOYckJljLFu#uyAbXi;=v*LVD(M75$A+DK(61*0+||+ zO#Y$@sB>d-{im4#pP|UM@S$gv%k^1GWIbf?$YGna0;tP73@WDX2<)mL zE2U?IRcX)3Nb%YQbEi;2=b4$AFYc90J3xcO(t!6##nJ)t*EFtQ7@>zw<{o!Im(?BG z!RfEwx^?Rndhd|xr(Oo5S1okGvZ6u-#{-9 zOmT28tgqj(BheqJ_M9sb)Mx^V+I-qO%jxv(mKZiRE( zrPAROIA1Fgi6iE74CQwW!jl@w_*&P=3H7qt?Aq*KViPtQvliju`dmx6d=eM)Hi5^* zS(mM|{^Ga5jMPrVL!V{D&Wun34>#C)E?eBtWV)ddA}AFK!_qH5$T zpFV3!+O)K(a`6=kh+zo9S0)k(mfE<4eZ0d0G6MsB16PMg=P^#+StK7WYlbRHUVydUAI;E-R~P&J62Gl7y_I`o?SAFv`*d; zm*%Tf6(j?HDfKT zYiE2Nuy$c~wSv>kQ&5^Kln}~KlfU(}AiBJDhTXgr$L0p_GPl3I!vo_C$=$+(tbYF7 zc^VyD>{e@Vg)(kQ7U*-ryrqdUU24t2+>&g6vTCr_HfmN>h3e&oVMG5HAnHk0Fexp8xhgFCj)=o1?2M{bQ= zx`oZHS7G#1FF(EgQQ(XkU1{xAb?O1ikb48=xyZaBBGPGfrPJHM=bW(K)WOb;bqguN zs}+p_%;{&r)AHWd5YT=(5tnF(QqRi=uT!v7(@UAx6mH+Xeg7kmtX<2NZZ_k*T(QZt z*%fSO$$wlItE=kp73-V3wzkK(U{jqP-r7&k{mPZsWpaq~c&xq#B4AV2tl3$!Os(N* zbI_eicNu!V=oysEI}yJmm~>7J9u&3PYec!@bHLn4JvDBd3Ur3qOe6*xJV+VOR5iOI zaP-+TW@gS>J8K@x+4n)3Lzw^k1U)wf*Uvgnor>Jk_>J**ZrF=3e&goN2+}#eD-M5a zWaQQ@j1Mor{PNR}Hd-*v-1dk*Z)$LIP2qM$+#8%m$Cw{)X>i4^9R_vA+hy`NZLUG~ zDv*9vkO%O=!tEH~DVy`FtF02Rs%mv%A?K)V-~QBrr+)khXK18N6B?~h9b^oX7q}W5 ztFBq!SSN_Ds&O4?^c#m9$ahn;w}VKk=2PrvrQ6apmOs}wb6_>FtI@ODjZA{$VP~Eo zsg}a*OH)Gc$1_0aj?O)Mn>IIrr(@FO5iQ8~jIQgIeC}iM6zahFv{^GV_bO>lGAGK< zzGjS!F@59$IQ-HDqi~VA95y$qkJ;;OZQjv)*!%)uK05NstLM(0effze9tF{^!e6!0 z$#ZM`$`zPe0+Tmbz@7SBQTI-`@~!QH`J?UYSqDd7pq`8ivW1y}ISsYoSb9}MWLeO9 z`k)S#_-$=JeX9t(^uom&soO znM;koa)#cwA^bw%s#AsE^!K~psM29|1Nz9hb1(n&=|>-JRH=jEJmR;D&Ktb@rd_hS zw7GE3YFEy0YHxQ%ZuGH$X8`!i7LTUS9j|f!zwuwG-%t z`FT^zq0w9o%@l>)iF3B_a5i!;0m$7DqaGg$sRcN{BMui#DmI)$W3DT8EAHl&M5m(r zmT#I*%~-5SLR&G-l<91?YA@qAX-+C)NGIduk`ASMC2Fj{xa=(_Bpf8^1wP zxR^n#vAunL9S5L?*E~#@vvT38hdDbEAM|%5hmt)5ySKpRo0C0I?)*KBx3kEdJ?<-J zX!Zd9?(5Q}&pDBxHeHLX+nfSs=>3#;i>};7mf!7ADS^(5C#8xqoM)b+7@U9}j065! zv!0J|G;NB7rloOSnr=e*!PBRQrO%W>WAW2ic)RJMFk?5z^^}osXnR|4-qp@K<2Ogg zM}&2VI|2P~A6p-@=9|R%8ax~5vlHQrxi>f`uB9Q6=p5!-ZQ622M>ki(YsJ6|9}O^P zT64&`Q_tAw@1D-@W6<$j4))l~+>K1VutFz?V zrOmaaP|slHTTTw7`LtQ^YVO&`;^rd3-3{LnugIQWwz`}e_-%YukmmcFET)4lh>OVGcE zP6M9wGS5U-0|bbb8_JIrI##T%B@{5F#S>;z;Ldkyxx}SQnt7JKvU#u z=Vi^zNXOZ%mEiP+wR_j@!wn<*L1tEll`?(h{K$Erd^7;K1Gip*V{hru(6@QlV>g$=YIRspZ@TN{rz2Ct5z9u04jsIN4C9~Be%iByg@kUl9-9kZXgTP9^2YZ zlqW8O$)iAj4mRK8a1Nt4G~iqT9VlN-ls~@xz|O;mjvo4_mktu?1UjL&Depd@97ra} zTUv1^)bSo5ujDH24MaJgahvWum;|BY1^*fxr7Gk+7kCA-d9jczY|AXpKKlF9Aoj6L zW1lZ^Ya83VgbY>3Iy6kGIFSQnz7{y_~q>!XpDw zoNMO!P$B{6k0;0Km9VEYrw4Zkx1&c7{KJ7GKYsq6S@YPqc@z9Mo7mpY=As?=sd#&H zLsQ)<4DGx)wW@NA4}OHN=ioj#fM3)SkMW`^s3=yEyVSY-_8^09e{ObzlQFCpo$2>= zHd#5>wQg3~x_b#;!yVWhCO`1Yc(%>F zG?)|PxET|xZ@=Al zIYAz;GpIL+&y_xJaI`K?mj|ceegn};uf3zYhfPE}5}byNhjJi8gR(MBzB{DzBp8<< zOtfM&fMeYSur92rq0_z{L;Emne)PbBmw@zpX3Z`x7Ro{W5C<`Rbv!|&$LdzC!DAKv zkuA;b0(w_h3?Jj`@q0P6W7LU}&mq>t&%(L!d9h|96T@a65A$^;0; zQBRj4zxj?HfxkW;GI(h6cisNGb^x3Xfj%-ab`e1T?N5LA_75*ZI)lttkv;JTZMIBm zi-qArnQo-ssn1$l+ctLh0KMH@91#dsYl+Lr%L7buUEv5nU|8QxljFRBq;lRoRlg1r zv8Hi5JUABg4Ih=&U)sNK-?Ul966Oo72Q4SB^Q##W0GrF;_y>aACDmo}4qR%1M5Z-p-fyMa-!wdI_{t)H|jvOGH4||wj2w^@(OO9K_msMviF!x2o* ze}IuY{>fckJK}MrS(29%M0ryaM|RNpCd2j=!#QlOzqiO%&j9l2F5X`34Mq=(gL4$v zQHMR)EnE6t8F8M$!P?{>#)$8gq%4hQozAEe(~CL#+>+^Bg~3VpTKk5~Swi`K6*kj- zJ8|*^On&ylg-Z&-K#-4zxONVke{u3GbvNad@iEoRjg9^Dx!?Zw{SQ9;u&=ux`WKRy z`d0~bSK|&y!P?C(_Aa}(>LX5Qu}*N%#K~@mwhr8hHAto_1K9AvFiDcjuR%Z$_TrBH zp=7+j9lwVz`{O%z?mT>S7{1DhUz{8Us~_0E|HltJz#0x%oT@zD6mM&1!d|PhTl9dF zv{u2l1FVG_1`IgW zP$(ZWl-nQ<%)*Qyb`9_z)!}IF#`AX#=??5Tdwk@Q%46Ziz5fAi-WTr&Kt$?fbU4d_ z?`}9Zo$li9aNOAuObg)lCiyTZ^Eog?p*#e9Lp$vr8gLDS1_yb3FiAHH!#g>*4&ypZ zj-mbMCw}!S{2zx;!hPTW=@U_Mn-(KTNre^J;`g+ z&byI)d$=bV{W|MrM#<>!zyHC%ya}TxT8%BqmmhujQf2YVyi^saWxE2N9dy>6_ z0|YOOE-Ix42hN8E0+=TUMCFvv$$`NkYG@vcC&=jA8)@@H$A*7#V)(=v++p?M15Z6( zue>^^z^#wPtVs>Ie2v@<_z?>4;7HRNmn^7v=R&aKSX~{&Ic&a3VSA`G>osG4Y^!v0 z`46jui?DoXEzj8xl|59p^r2J^UwYhv?++QukLTd4f9dh+gj$ZSC?1?MJN>0Iaqjf+*>>F%OiUMrc*w3Z0@duv76T~jgB&- z4x|6;hri#m?JA7!++s>};z{bvi8QCw9JjNErc(>(@eVr*>d8K`_JEKM?xyVrc`-o4 z_YmjWOXu3>&{wURE7ZycP2eR%CmrfNm5;^M$(r?0elX>9;i2Xq<9>2ex-6tDy*8xj7jS=4|@6ckhv(>{ltfMA{i9 z%$ZfWFgAXPIdY#LPa*OMpL-KKL-XCcw*%2eT|Wv&hadOP|NQ>@|N6$8dp_*zr2t-~ zq6rqn*)u3_r%3k>Jbk;)Ha2SC+{Xuv-rd*RJCx|_O-d#Y&|w=Ga1G%==Lx8De4qyp zwXCn-E}I|LESx|53IiFCK79De$0^+{W!}Y!?d|GZ0wMk|V+Sqr=(^)l`8c7nveM3l zU{_T>BzsMDbphwGXr?-wgsFXC?J_HFpFHWnRV0^&21^m(qHtK-arr|_gDkrH2wwZ~ z43T=Rr|Iu02IttCx*Tr>c`Xa)9K~Q@z|~^aZ}8dauXASkFe{(|bl zId*s_)3QV^*_;gB?%-=k2F#)G1@m}}C^zEAfS_<4L-H6w;I=OkpBJZRMPP2B5`oxI ztceXvLFl=xkF#=zY(u&0$R6?5Cqdl3SDc*ja;LUyvr9supj z-ezU)rOlsz9^?8^&R?+FH;b{4vZ`%7fcOnYTW*N-e3hYpmS1r-)46QxcmB;$;Ru@ zE?O3k&IImK|JM*Rp3b zV17^|yQ1uxjz(cVX2~?k@bMcrZ%hWeN4$641ONTDhdJL&@Jbm6p#ff=m2`( zAl&Y)TMg#JCkgaFocZ-@ClBx3{re4789`@IY<1CX0NXC9YCwU%WpY{%Q&+<5@`JSg+by|Xg+J+Dbh zKc{rnq=i?{k3gGW7$3)Dd^DoXQ`Puw2ks!P^6u@(NjA6>=R~>)ee50K{7-Mb`R2B( z$^Is4ben_D-s}$NZ7Pm)Q_#{t-Pm4(wa&ec60ny(^wy(PkH7!7kFWjy+8&JV$(9Cl+k?bf zOX#?_c;B6mq+o71XSKq%K0XGna06CPLWzsUHwfgwV6sOz=LWv~`u0bkhRtE}Q-b-g zhKCP7v0a_y#N2{;Bh*(H)EEo)@TA+$Uc#;G#oF-RLjS%=RL+E&VsJ#c;@`#W&NQ2E zjLbc9J=TeHjLl_QfWsY`%-nWhWdQONl0S~YLbWm_zk$(zqjb2Nd#3WMU=BJP!ue8e zGP$)c%gCNLPjU8XvqJVjsBxaqgwL;oJ~=Ga7^OB7EX@csM-76Zk`X zg3T{o8k@NO&L98y`;V`Eyyy2Y`cSeZM)q72vywQ8Hs`Ew2=woo*n7*s zz_u%T0bvjAQjA@6-b(Uqk0&V8ShZ$Z?nfW}DNPQTzjor+!1*vyP7b%KH!wNHIp4uI zFRHApTLlpgCmvM3UV&nAxi87*S@O#9;r2`Y-Zw1(#y-!iF6nLkq!@p__B=Y8UtL0ZO-gj zvqkKgmQI_ocP+&E!9#~mG5~k#lwrt=WqaqfbBm(_@19*%QBpaiVp?Xd6XuP zG1^vRVMCYrx0HHib(P8=iw$1*BWKMd&}-$P<=FCOLMz@0<0TY{M!HY+rRzo%P*fgb@t3_=T98lxxJCjH}o}_Uy58C{3IvOQiNBssH$!~ zGv<`#j3d}|d2QV;C#uQh>FfqaYr+yLn%9K>Kw5`8(Ux!F!RW3FucwH1TAuxcmOk`Q znV8%VEJo)f1(zGo^yn-p;#`0cX#4PgAzD0koew~s&m6vO*-*Pi3(-oW^)tCcZrPLw-; zeOH5P>`j~#*;gpbcW&R> zB{3e4D{01!>RkY2PD^N z@ujX+w|x}(EM+%@_rJS_6K->y%s?tnPbZrzb(=M_*ztLGiJS1O8h3pv={P-|9c4Hv zjmI*l?PX>2BS$c_s~bDx(3+NZK{n^;9wGEeadgk%QTmSThr42Q)y@Iu*#F~yeDdk1 z0Q#rTUE4D-lxQWLGr88>;M3=H;2RiwcllJ9obuZU-LIe4x5b2buqp@R>@6);GvA3z z#7fWy;J3&B_U#W~^K<7;oj-f_*x~JsFnRlW&5;BD>!A>PT^)V%Rb4@iyEUSt!JQ~y zZ#8yw+3}%f)8ALXMCx>^r$1b9Dwt7-$E$N7oU5~AE1>gQwP2Yrw8&ocuXeqh#x=UlX9^6INrSb?k5ELXV*S|?ivJ}1=?JVOoPGPZ#VdIna*wj zog@tw*KNRZ<8dd+2NhBU7{|FWeSwb{Qcw|-<<#Z#EKoi%$3>#5c0jTh2lb%kTDmeZ?ePM9Q+t&Zcj0aWJ@_KL@8>0{y~;OM%UAjyn-P5sdN9hl>dGcZ17f zB6t}Ov*@E^BR2r_cmItxC(^IE(Onhp0(TqLId=apQZ>=A>+b;c&RspQ`oQLaXSCk= zwqBN&gN~W+PP8QZl{N<_S1w%BupSo)&VA-b)aSiD-SHp(4mN-Px9D{KBFD<+Kv86`kv(qXRzoplhr#Eca}|%(hFZ*y>v#p5A9N-FH2Vg za$6=uv(Lrn3bm^W?#O;kR3eujJ4LB>;rxY*d}<=YMOCzqk2_k9GWP9oxOWFF>K;U9 zZhL)hM<~(x_RpUH=wEz#?F$EVmX)#Yt-&U$(da(IB7?)^x(^QQl0pZWZ|>`qoQEqw zj%5iO^?B2pE)MPS1o)gj+!m_y?s($u4?g^t_dj_5-1{%T3^G@&JfVnPqGKc7fKCS0 z#o3w=?^U~IsSi{NxJi}BiEZ}y|bufV@(5N1!duc^5Y?z<@6TIOQFRlXb?ZfGa3 z^A!goZ(*h5cVqDAp~xE+WK1E#iSewN(*X0J!YTl|)x9yROQg@t;1x*1nZ;VyX=|+{ ziuLT!X@t3o;4X^JN7%^KBmL&6(XtDtj)#mM!2Y(&pGNsU#m}D@r&ya9zy0nf9_U}l zjdLEipT=UO?q)90=9I3m#v6SApq0xk#$#)`x?-NGg>+U(FvLzBK#X@MI+H!vaG$@yVm^a|yLy21 zqP$JD>>pENZk7lgxHdqCK<6M&oO@b#@V3$5POUzP;LB&*st_2oIrn*5h3h#UCT1ng zwRE?w36?dlIFqYYTr1DQTK6Vrb-3<=dFQT9GWurTq0k2gdwOv0 znpH}`*Abd3I)~P;Tf>FbZXbN`)5o@UsbxIV;vF3ux_j)_ zxj|Fhp&9YR6z(R>ITdmtYufGf?&L;G(X-n${we(aEBF-yyW;K5HPGpbh~%g%Kss9m zK~ys<;^a5q>6xO(Q{M#g+`p!NEV#;RpQ08CS-|i*E4?Z8;@nkP%5Nvm8EJ=S2|kC@ zj-h?u-bbES4}RkO4BU1b+DAsrb644`!sMKZ>PQ{74R$BH@or?lgZO29hw}+%^N+vy z?9*#s!gb$sg;^5*H65Wlsm}W@2Xlw>UA-2E>+S3ordO@1B;697iooejODh4q%i`^V z`43pdIhHA!5nDu0MJi_F`UfFSn{^&8kZ-{qWKMMG1F6HSQ)|IE9 z&6(q~-O4JI=dPuUO0O9HwKy>6n_CaKSu-=;%oPpoM-Q@kgk9I6UrFS8T46h3T_Z%BSO4ui-p0J<00*EiG}%X_9s420IZWZ%^{E_~jqMZg(Lr5rG*8vu9`|~kLcO_}EUwymoZ8*fp;!P>Zk-1h1BmbF$|s>4 zhr4aa+wa*fxjZ+r*ujgg0-BQ&d~YuB+`NN z%xPqEbr;xg1?^|foR!z^+;(Sns&rPeF;ec~?GtQKL*MqGe>X_6MxjoB{l?AFTcZ%@ zw{L&)$yc9z@x>P(fA;BT&;9Ay=k@^V+pIKQ4m&5VG&BST_c%A8E4S9;VNRT{veGq9 z1SgpT=A!dwb0%S)xViK zx3e`M;Oj7mnED^k^f+9uy9W}F#p?2jbK`22HUQ0HZ*$d;m#wsSZkqz})Hi+*n8f9L z>ooVgnNwy?x1MjsCD7vEEAhHKsA9JTJ!j3EK4-f6q0NIrpFPdNoF+f2q5agUS1_`l zC7oZmbWwzUk$cRk+Qjpl*Oe}T?24*%=h%5c?hS6*+|GdE@gopxuW*kz{{%Sy;!DUi zFgl?A?4E7U!tBW&#@AW!&gmmAg|1e=8+K8llhdKmH}=3?YX+M?ylT}#n4L-Z_Vuh{ zZ(7p?$FDOo5E#D9q5aJ_ulBQm-Ro>BbGLMQ=Y|&Odd*ein(C149jb6w&v=S+ zxa~aFndH=|ZixA0kD1&}r`WA#ka<&!<)O2vf$n*kEPMR;O1R-GwWCkmrYzjkN7|Zx zcUxuMP2C4--Eix+65giGUHNO^xi2%f9r7GZF29|OzBY63+Iyad(c!`|iF)z`>`gYO zFuyS3?<1p(#u=px?&A!-Ump(y`W=++axEz!SG=A-ck5LG{x)s?$rph7XJ3AK?JsPd z`rMn(?RjpSrhs*B2xh8AfKHt6>giN^4Q66k{r*+DS61?6jj~^{cA}g~HqbeUe{*l* zvHl-k{oRKj_Qm@x#7?$v-N0Ef04@|ih78Z)^3C;$M@Qlgk&E7$XD|CLGZHndzD3>6u#ZcCXR7O;1ze z{M=cu&4qHpT=Q6z{JyRU=M#dt@Oo$TJwSg%$WPo5n}f(lKQhPtKRywo!|I=Y_T|^t zz7DMZ>=n)Gc1iT65a)t81k%P1LbH?Uvr2=x-3a%(HSLPPk!^c>pOJP>CgP91ef7g1 z_OFk5?JdGKoRiKUnZ0;zLG3X1acik+_= z0j!WsgqPt$AiwKr8@Kf@0f|R{d@|yfXqj!cAP;9chm+5(%-ye;mcGfY8phUeROrz5 zT;+J*^GANNA71;(pTp)*=E|H?mycai#l)pCO*(?T#pk2f+4t?n*u=PG_CzSkC+-mF zx)x~i@tah6I)7sP7HxhTHYd)%f*U8G|K%;-X!K_>Tta*&H&T7OWID6wyI^h@ya#t^ zWPaSViZG|Sm%9g*G!Wd$b0C>_Z`*>Q9pe0NfB3uCAKOa7-QF(k-rAaI>+IObg87~v zww$wrIM&_4Z|~jQ-SZgEt<%zN_);o*Rk^dD4O_S;6D~W?^7&4N1@iMN*d;%Z;>X`J zCBE|bd$2kXU&;-(?l4XIUU;_KZnoHb3uADKzY*q|h-SfbgTA@)owyWYT?0O zTzoEFPsbhl+z9>8BJ{5W^iMzg`Y&I<_14$8%jnPUp;S*YtxnHfBYP*K?Hf0CYuf`4 zuBByFWyAf#`SSb!Hy+;ysn^v(m?t?e)!2N?0MvQ=j{dhV_p9Vhtz{*@6^$X8Z&dG? zmKNuu+0o5?oxP96ZE~6|&}!4tTa{>U=_H|ZAQ?26!%?Uz$V)2@$vL{`sa>V(4&Y*T zw@syNjpN}D`*VVCVSJs?^;B+aaV&Nz8y9k4=7PV)^B8}d$2>dtGv&1_rRLPRNpr?s ztuOo7g>lB(o#Rf=-Egi+Eg*DqIwNusm43JScSAW~E*}6s+%1j^4(DHe@ztkv-T(6S zH*bCO^*7Gw&q=f;)eNRRV01G1MvU)b+?G{qG_qGZl=C5&ClWZPXV>5}o9VXq^>!z= z_V2jN=$qxs9HQI!Ws0daE9NG_E|hbC;A}YHJV>3}Pj=9GZ_(4DaF&|Kh*Zas9Zvgu z24^Ds4ycBZb|-`fh%`>uD>z<)_ z%>E-s4#MOIUpT1+(`*?`I_wv{Ah-5zN_@lOc#MyNpvP%-s`NmTyB%t9FVSa|BUwj+8bT|`?f2|o`h9JS{wIW8rGE~PjhyDBGE8mO$gg@_i@P*-yQsUN>#8tq#n#v&9ZqwF0rL!CkI2Y78b49a{ zk7$yb(K!p@g!8aKM*B{k1L&NHGDb2VzZnvGgvrgBPf_QD_{8`nC^kH<-}>ky0{&fx zb6FighrPd%(Z4aPL#o5&Zn2*3fj%df3!qJPaM+#CzI^%jbzeZ{b!jr@-@xXebG8-R zY89^DYnOo6XklFLQ0`#9xwo&cueZ~>*a_xLwz=vUr{fbg=@n!ynHH-Oo2Q^uV7?1j z9iBbb9mJzQc<0Y(+;+#M&wZP*Ne$v0qvw`nxK?nk&8WJ%Duur99<5yuiy!3jr^=g? z&6PIyiu~d@$vo%_cbyBZFbjSI&ydk?m}(=U`HV8XQTg@j6W8GZj84erIPk9Ha|d)7 z{hP1x{L?oibq?@*_B?xaAnDu28KX;4YZa!3W{m6{*ek*2-@pI+cr2*ov=e%8GWjzD z+qO`gbAGs+E$-R8r7f|6F>}V)TVm~TBXb-B$~hly%Rn!ixT+GaF~%Br7QY+s`@}ox zoVjy`5*lhMVe;})FRN4dcx6b*X5y9a$@22r%WR*|;3RiQx?a%dX)3MLIjVapUZ>VW z0niQNOUstB<5(cj%~>bltx9%Y*0g<$z^VD)!P75zoD=0%<7_A&3))OD#X_Jn{5sA@ z)NhXhJCbs<;2TDC4i5x6v>I(bo{DoC{To;u4-WBk=V2h5GmdtBKZ%jGt+=WUb z9_`_7>zLcJYAl0SXR-`jD4Chl_Nfuv5yAZQp_80(evxy|Y4l5@N|;lgbN@Palt90( zU2OR<#ZBpLdzLM|8NN}}RSKP>!Z@oXfb&0$n#~R8Us)`UM%Tl!`deJN?Ag8{NZ*Dg zTN9m(zHwvQ#!mK;a>1D8gtT{h?@TJg&NBEdkom3f@>r*A>$ov9-qHZ?yN#Li zL|m!z7GS(hz30@^094*f|BYqrT+9tmKAM{wo0U>$ik%bO@mr|S>1fteFUl)UcasM- zovciPTyJfML;8Cw-9Gnpz%Z<*`zSa=$Lu73Cbwm!5Zu0fMA(?bbGgZMBlIANZu4ET z$}_Xpx|TrzxuWgnwG-m!wC=`rwF4oO(_N?COqdhk_Swzra^CrgV{v)$E`#Rs=FaTn zL^?_R`mI0w0b=d83%-6803G*l2zHI~Ks&Ae<{o%*s#w>AHOg~7eFV;Yc0imcuOb>* zD&y*C7-~;6uUb`UC|5eov$0jRSvLtQuwm`1Qf0k#0oZ(ofDUG1B3XJ(q$?x&m&Tj2H8iz=5;kll0ms5N+{|82?~3SETGjVO9zB9+25o=2+T z$no|Q;PqP{{gsipcmKoV{40ygdm=H@zO*}49TtBd0yo0X2=0xgJN!zUaL`s``x>5hPnu-(2Q?&6{^$f$xwXPBsq&x~eKduiXT@%}({LB_!0#@#z`y_tdjxGd6n4M?g{;iPe1=02>7~JK$fA-loUjpbvJfZ$48QoIqwn_^*eFOZr z|Eu7-0&r27xA!ZbHu%hD0=B2!p|oU_k;9h~Q9liQBi zIYu+^E>gelh}{&r+xizm+!$Rp$C>{T`fy*lv0V`V@^jf88^vedu;G1|XLLAl|JPKx z9>(V1Ur+>lw6sudG0skv4OUjQ`c|!qww|3LT4Hg=(Zt{JRtj@H@V-q!nm&fvTU(uu zC+};0R8__`N$0cbPA96vWVg!l)jSR-Zr$3oXiB*W=~RU-Hum%!@^wJc_PN`JM_pXb zMd$qC9Cdm0MQ|a)eZ1W&sI3e(X!}|&n8R&1Iv2{BUokd6&$YBJTpCrRU7OKyo4Pa} znNB`oK0F6@qS}1-D8N(p4d-zG>A2te!+(BsE5&a&oPQxI|3*0f+@KDm!|2fIS9YuT zeM3v<203sBbB5S$Xm>Dg?O>=~7-u$3t=5~ZT_eS{D|Tb@JOH^9=-_k1Ifc1Z*16(l zrqPIZYZr&>1gx+2W4+eaVi%i|aaqOW&qU{d{HONDB-@+M zJ_bFbkok; zl{Z%|ePf#%!zo)%70=q31b!*T2m1iO0uo+L=h&%?tw$4m1AScb>FQ9TD1Q-jx`}iz zsQs&Hb^FM_1fPY%J>2o_obv?Q3OohFx9P zN2bot+mv&cG1tg0-`!0`PQ|XHaZ8ptf8L*=gVEFJvnz&oeH=K4&Bt$=&BMX{GnqNS zx!!$dNtZo)p54tNXw7JIWiiW@Oml3$fXuA|nI7v0+u^l02X)Jsdp?nKgWJ!coi5zT6P$~B%9p`8d9LjF z=$Ky*^`;A~PI%JBfUTOi8*V${%HD!=q|>iEHlJ{@`s=c}d?zqkKoN-GEM;e`Gih194x;=0x^4F!z^)`N#6#F}f4! z&vBt~7S60%ca=Fser?q5PO_eU6PS1!HD+RG@<=3;XI zI-Z>4qA*`V=`^*d;cP25n!Pf>)nKk(POPbCdad@q3cE)FYyZU=cQX5(R9`Vg#c=HO zzYbk~|M}Njq2K;jqtNVAA~i%WGpK^cGJ~v>tA4Rc8_VX zyE_I8(*sZTz?bieH9J|3Z|T&R@tJ6%KBr6@8r(d%d0_V-$X~t0hhTLs6LEDY8HZ3` zF(VCs=s;YDJCVKUuIcmW0Vl*$k4dGQZs+tbse*j%^w_b;aB!h#tAH0d~akrwvMcm<=FSWj*%-_06iZ)@2^;M45#q_n=wbq`W z)vj7;hp~2-Ik&}ERMGzGC>J?Z37k{bRN_|M=H(u8C&MxjAlDeqeHa50@1f2ij z`ouebPEE3W;YRmQ#ps`YCdF>yxv$OWjJ!9ksjMW8o4Mz6bMO4BdPdY$uSQcjP3_|8 z#?7Mi-~(35h|**HJg$joJxr#1epg7Ii##PC>*NYB@fNMbq6zM1Z`V;4m)YgyW$pL3 z#6ahZD#~-5M4!ya^2h^Tj_gG^Jc!RvJ|o=cg3Iv7dB^x&>Ylk6$z^fw;dkb`qk5ZD zn(>=V4|7YRo;)R+pBp*vYuYc}x~@AOqqmIk3pfalGQz~Pe_;FkiGc=;XQui zw%fn%OpbT5Iit9@ZvFND{pUxcqc{H?@_EGQ3d{tqJE3mD8K%>BWB81%stlrU_u6KD z6@;2F9Pe1KJ9adL$Gs@yC~lWQtKOPWi*@meVD)l$XLl!Sn48+|JXaitgFP7a@kx7K z7w%k2uOmrmju)=%!(YSIfcmk&HP%(1zsSLy8Z0*z;-X|8bvTY5O?l&-c1yh;zvJVy z;(6(|rnc(}UgnlTuPxO}PHk8!U6PYy44?f=cyO9?e(>n|KN<@;ID3q z+DqzCgh!6}olu2GPV+w>ITGsjG%j6Fki#=C)gh1O5(jlWmA}(*ZrJJFV1B?*KFsWj zq5Qm%K4S1D%stK_s|9f4++p~J052pP%{NrMC5Ogi{nayr;EM8K&#OZTDUvkmE&B@L9 z%{2{^m5a_zv&-ZvYnLZrK7l&ZXvs#-H3!efVpYrUU$w?lzlhvL?VZ

8Y}O@;Ums+3XS@;9M~04il$2rS`x(!#Lrt4{FPS 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

  • BP?3o`+p^hp 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 z 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