--- title: "Aggregation" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Aggregation} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 8, fig.height = 5, message = FALSE, warning = FALSE) library(dplyr) data.table::setDTthreads(1L) options(scipen = 999, digits = 4) ``` `aggregate_estimands()` averages the treatment-group-specific estimates of `multiple_treatment_group_analysis()` across treatment groups, by event time (Section 5 of Leventer 2025, [*Identification of Child Penalties*](https://arxiv.org/abs/2602.07486)). Symbols and row labels are in [Notation and output](notation.html), the estimators and influence functions in [Estimation](estimators.html). Equation, section and theorem numbers refer to the main text; appendices are referred to by name. The examples use one simulated panel. Treatment groups 24-30 at event times 0-3 use control groups up to 34, so every treatment group has a cell at every event time. ```{r estimate} library(childpen) sim <- simulate_data(20000, 24:34) res <- multiple_treatment_group_analysis(sim, 24:30, periods_post = 3, periods_pre = NULL, verbose = FALSE) ``` The result carries the person-level influence functions that `aggregate_estimands()` reads, so it is passed on unmodified. ## 1. Aggregate causal estimands For event time $e$, let $\mathcal{D}(e) = \{d : d + e < D_{\max}\}$ be the treatment groups that have an estimate. Since the control group is $d' = d + e + 1$, the condition is $d' \le D_{\max}$, the bound set by `max_control_group`. With $\mathbb{E}_D$ the expectation over the treatment distribution, Section 5.1 defines $$ \rho_{\mathrm{Agg}}(e) = \mathbb{E}_D\big[\rho(D, D, D + e) - \rho(D, \infty, D + e) \mid D + e < D_{\max}\big] \qquad \text{(eq. (10))}, $$ $$ \theta_{\mathrm{Agg},1}(g, e) = \mathbb{E}_D\big[\theta(g, D, D + e) \mid G = g,\, D + e < D_{\max}\big], $$ $$ \theta_{\mathrm{Agg},2}(g, e) = \frac{\mathbb{E}_D\big[\mathrm{ATE}(g, D, D + e) \mid G = g,\, D + e < D_{\max}\big]}{\mathbb{E}_D\big[\mathrm{APO}(g, D, \infty, D + e) \mid G = g,\, D + e < D_{\max}\big]}, $$ $$ \Delta\theta_{\mathrm{Agg}}(e) = \mathbb{E}_D\big[\theta(f, D, D + e) - \theta(m, D, D + e) \mid D + e < D_{\max}\big] \qquad \text{(eq. (11))}. $$ The package replaces each treatment-group causal estimand by its 2x2 descriptive counterpart $B_d$ and the treatment distribution by weights $w_d$ (next section), so that $\hat A(e) = \sum_{d \in \mathcal{D}(e)} w_d \hat B_d$. The rows of `aggregate_estimands()` are identified by `method`, `estimand` and `agg_type`: | `method` | `estimand` | `agg_type` | aggregate | $B_d$ | |---|---|---|---|---| | `DID_Female`, `DID_Male` | `theta` | `weighted_avg` | $\theta_{\mathrm{Agg},1}(g, e)$ | $\delta_\theta(g)$ | | `DID_Female`, `DID_Male` | `theta` | `ratio_of_avgs` | $\theta_{\mathrm{Agg},2}(g, e)$ | $\delta_{\mathrm{ATE}}(g)$ and $\delta_{\mathrm{APO}}(g)$, averaged separately and divided | | `NTD` | `rho_effect` | `weighted_avg` | $\rho_{\mathrm{Agg}}(e)$ | $\delta_{\Delta\rho}$ | | `Conventional` | `gap_theta` | `weighted_avg` | $\Delta\theta_{\mathrm{Agg}}(e)$ | $\delta_{\Delta\theta}$ | | `TD_E_LOGS` | `rho_effect` | `weighted_avg` | $\rho_{\mathrm{Agg}}(e)$ under TD-E-LOGS | $\delta_{\Delta\rho}$ with $\delta^{\times}_{\mathrm{APO}}$ | | `TD`, `TD_PR`, accounting rows of `NTD` and `TD_E_LOGS` | `gap_ATE`, `gap_theta_pre`, `rho_obs`, `rho_cf`, `share_parenthood`, `share_other` | `weighted_avg` | weighted average of the group-level row; no symbol in the paper | the group-level row | The output has one row per event time, `control_offset`, `estimand`, `method` and `agg_type`, with `est`, `se`, `n_groups` (treatment groups with positive weight), `ci_l`, `ci_h`, `t` and `p`. ```{r agg-rows} agg <- aggregate_estimands(res) agg |> filter(event_time == 2, estimand %in% c("theta", "gap_theta", "rho_effect"), method %in% c("DID_Female", "Conventional", "NTD")) |> select(method, estimand, agg_type, est, se, n_groups) ``` `ratio_of_avgs` divides the weighted average of the `ATE` rows by that of the `APO` rows. Section 5.1 shows that $\theta_{\mathrm{Agg},2}$ is also an average of the $\theta(g, d, d + e)$, with weights proportional to the treatment-group share times counterfactual earnings $\mathrm{APO}(g, d, \infty, d + e)$. ## 2. Weights | `weights` | weight of treatment group $d$ in $\mathcal{D}(e)$ | |---|---| | `"sample"` (default) | the share of persons in the group: $w_d = n_d / \sum_{k \in \mathcal{D}(e)} n_k$, where $n_d$ counts persons of both genders with $D = d$. For `DID_Female` and `DID_Male`, shares within gender: $w_{g,d} = n_{g,d} / \sum_{k \in \mathcal{D}(e)} n_{g,k}$ | | `"uniform"` or `NULL` | $1/m_e$, with $m_e$ the number of groups in $\mathcal{D}(e)$ | | a named numeric vector | proportional to the entry named $d$, renormalized to sum to one over $\mathcal{D}(e)$. Groups missing from the vector get weight zero, with a warning | Gender gaps are aggregated as in eq. (11): the within-group gap is averaged with weights pooled over genders, rather than differencing two within-gender aggregates, which would also reflect gender differences in the treatment distribution (Section 5.1). Only `DID_Female` and `DID_Male` use within-gender weights. ```{r weights} w_named <- setNames(dnorm(24:30, mean = 27, sd = 3), 24:30) bind_rows( sample = aggregate_estimands(res, weights = "sample", methods = "NTD"), uniform = aggregate_estimands(res, weights = "uniform", methods = "NTD"), named = aggregate_estimands(res, weights = w_named, methods = "NTD"), .id = "weights" ) |> filter(estimand == "rho_effect", event_time %in% c(0, 3)) |> select(weights, event_time, est, se, n_groups) ``` A named vector aggregates the same treatment-group estimates under another treatment distribution, as in Figure 9 of the paper ([Replicating the paper](replication.html)). **Groups that drop out.** A treatment group has a cell at event time $e$ only if its control group $d + e + 1$ is at most `max_control_group` ($D_{\max}$ in the paper). Groups beyond the bound drop out at later event times, and `n_groups` records how many remain. ```{r dmax} res_cap <- multiple_treatment_group_analysis(sim, 24:30, periods_post = 3, periods_pre = NULL, max_control_group = 32, verbose = FALSE) bind_rows( `Inf` = aggregate_estimands(res, methods = "NTD"), `32` = aggregate_estimands(res_cap, methods = "NTD"), .id = "max_control_group" ) |> filter(estimand == "rho_effect") |> select(max_control_group, event_time, est, n_groups) ``` With `max_control_group = 32`, group 30 has cells at $e = 0, 1$ only and group 29 at $e \le 2$, so $\mathcal{D}(e)$ shrinks and the weights change with $e$. As the footnote to eq. (10) notes (following Callaway and Sant'Anna 2021), a comparison of aggregates across $e$ then combines variation in causal effects with a shift in the composition of treatment groups. The composition is the same at every event time when each group in the aggregate has a cell at each of them, as with `max_control_group = Inf` above (`n_groups` is 7 throughout). ## 3. Standard errors Let $B_d$ be the estimate of treatment group $d$, $p_d = \Pr(D = d)$ its population share, $P_e = \sum_{d \in \mathcal{D}(e)} p_d$ and $w_d = p_d / P_e$. The influence function of $A(e) = \sum_{d \in \mathcal{D}(e)} w_d B_d$ is (the aggregate estimator section of the appendix on estimation and inference) $$ \psi_{A(e)} = \frac{1}{P_e} \sum_{d \in \mathcal{D}(e)} \Big[ \big(B_d - A(e)\big)\,\psi_{p_d} + p_d\,\psi_{B_d} \Big], \qquad \psi_{p_d} = 1\{D = d\} - p_d . $$ For the within-gender rows the share is the joint share of gender $g$ and group $d$, with $1\{G = g, D = d\} - p_{g,d}$ in place of $\psi_{p_d}$. With `"uniform"` or fixed weights the first term is absent; with `"sample"` it accounts for the estimated shares. For `ratio_of_avgs`, $\hat\theta_{\mathrm{Agg},2} = \hat N / \hat M$ with $\hat N = \sum_d w_d\,\hat\delta_{\mathrm{ATE},d}$ and $\hat M = \sum_d w_d\,\hat\delta_{\mathrm{APO},d}$, and by the chain rule (**not in the paper**) $$ \psi_{\theta_{\mathrm{Agg},2}} = \frac{\psi_N}{M} - \frac{N\,\psi_M}{M^2}, $$ where $\psi_N$ and $\psi_M$ are the influence functions of the two weighted averages, each with its share term. The influence function of `share_other` is minus that of `share_parenthood`. The group-level influence functions are summed per person across treatment groups before they are squared, with clusters at the person level, $$ \widehat{\mathrm{Var}}(\hat A) = \frac{1}{n^2} \sum_{c} \Big( \sum_{i \in c} \hat\psi_i \Big)^2 \frac{G}{G - 1}, $$ for $n$ person-age rows and $G$ persons. A person who serves as a control group member for several treatment groups therefore enters several terms of the same sum. The share term is put on the person-age scale with the average number of ages per person, which is exact for a balanced panel. The estimators and the influence functions of the group-level rows are in [Estimation](estimators.html).