Skip to contents

This page describes how the package runs the paper’s 2x2 comparisons, then writes out every estimator it returns and the influence function its standard error is built from. Notation follows Notation and output. Section, theorem and appendix numbers refer to Leventer (2025), Identification of Child Penalties; appendices are referred to by name, because their letters differ between the arXiv and journal versions: Estimation appendix is the appendix on estimation and inference, Proportional appendix the online appendix on proportional DID and TD. Formulas that are not in the paper are marked not in the paper.

Running the comparisons

multiple_treatment_group_analysis() runs the grid of 2x2 comparisons that the paper’s figures use. For each treatment group dd in treatment_groups and event time e=0,…,He = 0, \dots, H (periods_post = H), the target age is a=d+ea = d + e and the control group is the closest not-yet-treated group, d′=a+1d' = a + 1 (Section 1.3). Pre-treatment event times e=−(pre+K),…,−(pre+1)e = -(\text{pre} + K), \dots, -(\text{pre} + 1) (periods_pre = K) are estimated against every control group used after treatment, d′=d+1,…,d+H+1d' = d + 1, \dots, d + H + 1: the identifying assumptions are about each treatment-control pair, so each pair has its own validation test (Section 2.3). The column control_offset =d′−d= d' - d identifies the pair. max_control_group is the largest age at first birth used as a control (the paper’s DmaxD_{max}). single_treatment_group_analysis() runs one comparison.

res <- multiple_treatment_group_analysis(data, treatment_groups = 24:34,
                                         periods_post = 5, periods_pre = 3,
                                         max_control_group = 40)

With the paper’s sample this grid is the one behind its figures: treatment groups 24 to 34, event times 0 to 5, pre-treatment event times −4-4 to −2-2 (baseline d−1d - 1), and controls up to 40 (Replicating the paper).

One comparison. single_treatment_group_analysis() returns the rows of one cell (d,d′,a)(d, d', a). Treatment group d=26d = 26 against control group d′=28d' = 28, after childbirth at age a=27a = 27 (event time 1) and before childbirth at age a=23a = 23 (event time −3-3), both with baseline age 25:

library(childpen)
sim  <- simulate_data(5000, 24:30)
fmt  <- function(v) format(signif(v, 3), scientific = FALSE, drop0trailing = TRUE, trim = TRUE)
show <- function(x) transform(x[c("event_time", "control_offset", "method", "estimand", "est", "se")],
                               est = fmt(est), se = fmt(se))

post <- single_treatment_group_analysis(sim, d = 26, dp = 28, a = 27)
show(post)
#>    event_time control_offset       method         estimand     est     se
#> 1           1              2   DID_Female              APO   24900    377
#> 2           1              2     DID_Male              APO   26200    388
#> 3           1              2   DID_Female              ATE   -8340    327
#> 4           1              2     DID_Male              ATE   -1160    361
#> 5           1              2   DID_Female            theta  -0.335 0.0095
#> 6           1              2     DID_Male            theta -0.0444 0.0134
#> 7           1              2           TD          gap_ATE   -7170    487
#> 8           1              2 Conventional        gap_theta   -0.29 0.0164
#> 9           1              2          NTD       rho_effect  -0.289 0.0176
#> 10          1              2    TD_E_LOGS       rho_effect  -0.288 0.0202
#> 11          1              2        TD_PR    gap_theta_pre   -0.34 0.0241
#> 12          1              2          NTD          rho_obs   0.662 0.0124
#> 13          1              2          NTD           rho_cf   0.951 0.0202
#> 14          1              2          NTD share_parenthood   0.856 0.0572
#> 15          1              2          NTD      share_other   0.144 0.0572
#> 16          1              2    TD_E_LOGS          rho_obs   0.662 0.0124
#> 17          1              2    TD_E_LOGS           rho_cf    0.95 0.0235
#> 18          1              2    TD_E_LOGS share_parenthood   0.853  0.067
#> 19          1              2    TD_E_LOGS      share_other   0.147  0.067

pre <- single_treatment_group_analysis(sim, d = 26, dp = 28, a = 23)
show(pre)
#>    event_time control_offset       method         estimand     est     se
#> 1          -3              2   DID_Female              APO   17400    346
#> 2          -3              2     DID_Male              APO   17700    361
#> 3          -3              2   DID_Female              ATE     213    289
#> 4          -3              2     DID_Male              ATE     492    324
#> 5          -3              2   DID_Female            theta  0.0122 0.0168
#> 6          -3              2     DID_Male            theta  0.0278 0.0187
#> 7          -3              2           TD          gap_ATE    -280    434
#> 8          -3              2 Conventional        gap_theta -0.0155 0.0251
#> 9          -3              2          NTD       rho_effect -0.0148  0.024
#> 10         -3              2    TD_E_LOGS       rho_effect -0.0156 0.0218
#> 11         -3              2        TD_PR    gap_theta_pre -0.0132 0.0184
#> 12         -3              2          NTD          rho_obs   0.963 0.0185
#> 13         -3              2          NTD           rho_cf   0.978 0.0279
#> 14         -3              2          NTD share_parenthood   0.403  0.656
#> 15         -3              2          NTD      share_other   0.597  0.656
#> 16         -3              2    TD_E_LOGS          rho_obs   0.963 0.0185
#> 17         -3              2    TD_E_LOGS           rho_cf   0.979  0.024
#> 18         -3              2    TD_E_LOGS share_parenthood   0.427  0.571
#> 19         -3              2    TD_E_LOGS      share_other   0.573  0.571

Input data. data is a data.frame or data.table in long format, one row per person and age; the panel need not be balanced. The columns are located by name:

argument default content
id_name "id" person identifier (the clustering unit)
age_name "age" age, numeric
D_name "D" age at first birth, constant within person; a missing (or infinite) value means the person never has a child
female_name "female" gender, constant within person; 1 / TRUE is female and 0 / FALSE male; labels such as "female" / "male", "f" / "m", "woman" / "man" are also accepted
Y_name "Y" earnings, numeric; zeros are allowed, while the ratio rows need positive cell means

Rows with a missing outcome are dropped with a message. The functions stop with an error if a person-age pair is repeated, if female or D varies within a person, if a gender label is not recognised, or if only one gender is present. data is not modified. Persons with a missing D stay in the data, belong to no treatment or control group, and count in the totals the standard errors are scaled by.

Setup

Data are one row per person ii and age tt, with earnings YY, gender g∈{f,m}g \in \{f, m\} and age at first birth DD. A 2x2 comparison has a treatment group dd, a control group d′>ad' > a, a target age aa and a baseline age b=d−preb = d - \text{pre} (default b=d−1b = d - 1).

Cell means. For a cell (g,k,t)(g, k, t), with indicator Sit=1{Gi=g,Di=k,age=t}S_{it} = 1\{G_i = g, D_i = k, \text{age} = t\}, μ̂(g,k,t)=∑i,t′Sit′Yit′∑i,t′Sit′,ψμ(g,k,t)=SP̂(S)(Y−μ̂(g,k,t)), \hat\mu(g,k,t) = \frac{\sum_{i,t'} S_{it'} Y_{it'}}{\sum_{i,t'} S_{it'}}, \qquad \psi_{\mu(g,k,t)} = \frac{S}{\hat P(S)}\,\big(Y - \hat\mu(g,k,t)\big), where P̂(S)\hat P(S) is the share of person-age rows in the cell (Estimation appendix). Every estimator below is a smooth function of eight cell means, μ1=μ(g,d,b),μ2=μ(g,d′,a),μ3=μ(g,d′,b),μ4=μ(g,d,a),g∈{f,m}, \mu_1 = \mu(g,d,b),\quad \mu_2 = \mu(g,d',a),\quad \mu_3 = \mu(g,d',b),\quad \mu_4 = \mu(g,d,a), \qquad g \in \{f, m\}, and its influence function ψ\psi follows from theirs by the chain rule.

Standard errors. For an estimator with influence function ψ\psi, with nn person-age rows, GG persons and clusters cc = persons, Var̂=1n2∑c(∑i∈cψi)2GG−1. \widehat{\mathrm{Var}} = \frac{1}{n^2}\sum_{c}\Big(\sum_{i \in c}\psi_i\Big)^2\,\frac{G}{G-1}. Confidence intervals are est±1.96se\text{est} \pm 1.96\,\text{se}.

Rows of single_treatment_group_analysis()

Imputations of counterfactual earnings. Additive (DID) and multiplicative: δ̂APO(g)=μ1+μ2−μ3,ψδAPO(g)=ψ1+ψ2−ψ3; \hat\delta_{APO}(g) = \mu_1 + \mu_2 - \mu_3, \qquad \psi_{\delta_{APO}(g)} = \psi_1 + \psi_2 - \psi_3; δ̂APO×(g)=μ1μ2μ3,ψδAPO×(g)=δ̂APO×(g)(ψ1μ1+ψ2μ2−ψ3μ3). \hat\delta^{\times}_{APO}(g) = \frac{\mu_1\,\mu_2}{\mu_3}, \qquad \psi_{\delta^{\times}_{APO}(g)} = \hat\delta^{\times}_{APO}(g)\Big(\frac{\psi_1}{\mu_1} + \frac{\psi_2}{\mu_2} - \frac{\psi_3}{\mu_3}\Big).

method estimand estimator influence function identifies its target under in the paper
DID_Female, DID_Male APO δ̂APO(g)\hat\delta_{APO}(g) ψδAPO(g)\psi_{\delta_{APO}(g)} NA, DID-PT Lemma 1; eq. (3), Estimation app.
DID_Female, DID_Male ATE δ̂ATE(g)=μ4−δ̂APO(g)\hat\delta_{ATE}(g) = \mu_4 - \hat\delta_{APO}(g) ψ4−ψδAPO(g)\psi_4 - \psi_{\delta_{APO}(g)} NA, DID-PT Lemma 1; eq. (3), Estimation app.
DID_Female, DID_Male theta δ̂θ(g)=δ̂ATE(g)/δ̂APO(g)\hat\delta_\theta(g) = \hat\delta_{ATE}(g)/\hat\delta_{APO}(g) ψδATEδAPO−δATEψδAPOδAPO2\dfrac{\psi_{\delta_{ATE}}}{\delta_{APO}} - \dfrac{\delta_{ATE}\,\psi_{\delta_{APO}}}{\delta_{APO}^2} NA, DID-PT Lemma 1; eq. (3), Estimation app.
TD gap_ATE δ̂ATE(f)−δ̂ATE(m)\hat\delta_{ATE}(f) - \hat\delta_{ATE}(m) ψδATE(f)−ψδATE(m)\psi_{\delta_{ATE}(f)} - \psi_{\delta_{ATE}(m)} NA, TD-PT Lemma 1; Estimation app.
Conventional gap_theta δ̂θ(f)−δ̂θ(m)\hat\delta_\theta(f) - \hat\delta_\theta(m) ψδθ(f)−ψδθ(m)\psi_{\delta_\theta(f)} - \psi_{\delta_\theta(m)} NA, DID-PT; under NA and NTD-PT it equals Bias×[θ(f)−θ(m)]\text{Bias} \times [\theta(f) - \theta(m)] Thm. 1; Estimation app.
NTD rho_obs ρ̂obs=μ4(f)/μ4(m)\hat\rho_{obs} = \mu_4(f)/\mu_4(m) ψ4(f)μ4(m)−μ4(f)ψ4(m)μ4(m)2\dfrac{\psi_4(f)}{\mu_4(m)} - \dfrac{\mu_4(f)\,\psi_4(m)}{\mu_4(m)^2} consistency Thm. 2; Estimation app.
NTD rho_cf ρ̂cf=δ̂APO(f)/δ̂APO(m)\hat\rho_{cf} = \hat\delta_{APO}(f)/\hat\delta_{APO}(m) ψδAPO(f)δAPO(m)−δAPO(f)ψδAPO(m)δAPO(m)2\dfrac{\psi_{\delta_{APO}(f)}}{\delta_{APO}(m)} - \dfrac{\delta_{APO}(f)\,\psi_{\delta_{APO}(m)}}{\delta_{APO}(m)^2} NA, NTD-PT Thm. 2; Estimation app.
NTD rho_effect ρ̂obs−ρ̂cf\hat\rho_{obs} - \hat\rho_{cf} ψρobs−ψρcf\psi_{\rho_{obs}} - \psi_{\rho_{cf}} NA, NTD-PT Thm. 2; Estimation app.
TD_E_LOGS rho_cf ρ̂cf×=δ̂APO×(f)/δ̂APO×(m)\hat\rho^{\times}_{cf} = \hat\delta^{\times}_{APO}(f)/\hat\delta^{\times}_{APO}(m) as NTD rho_cf, with δAPO×\delta^{\times}_{APO} NA, TD-E-LOGS Proportional app.; IF not in the paper
TD_E_LOGS rho_obs, rho_effect as NTD, with ρ̂cf×\hat\rho^{\times}_{cf} as NTD, with ψρcf×\psi_{\rho^{\times}_{cf}} rho_obs: consistency; rho_effect: NA, TD-E-LOGS Proportional app.; IF not in the paper
TD_PR gap_theta_pre θ̂pre(f)−θ̂pre(m)\hat\theta_{pre}(f) - \hat\theta_{pre}(m), θ̂pre(g)=μ4−δ̂APO×(g)μ1\hat\theta_{pre}(g) = \dfrac{\mu_4 - \hat\delta^{\times}_{APO}(g)}{\mu_1} ψθpre(f)−ψθpre(m)\psi_{\theta_{pre}(f)} - \psi_{\theta_{pre}(m)}, ψθpre(g)=ψ4−ψδAPO×(g)μ1−θpre(g)ψ1μ1\psi_{\theta_{pre}(g)} = \dfrac{\psi_4 - \psi_{\delta^{\times}_{APO}(g)}}{\mu_1} - \dfrac{\theta_{pre}(g)\,\psi_1}{\mu_1} NA, TD-PR Proportional app.; IF not in the paper
NTD, TD_E_LOGS share_parenthood ŝ=ρ̂cf−ρ̂obs1−ρ̂obs\hat s = \dfrac{\hat\rho_{cf} - \hat\rho_{obs}}{1 - \hat\rho_{obs}} ψρcf−ψρobs1−ρobs+(ρcf−ρobs)ψρobs(1−ρobs)2\dfrac{\psi_{\rho_{cf}} - \psi_{\rho_{obs}}}{1 - \rho_{obs}} + \dfrac{(\rho_{cf} - \rho_{obs})\,\psi_{\rho_{obs}}}{(1 - \rho_{obs})^2} as rho_cf of the same method Sec. 4.2 (estimate); not in the paper (IF)
NTD, TD_E_LOGS share_other 1−ŝ1 - \hat s −ψs-\psi_s as rho_cf of the same method not in the paper

NA (no anticipation), DID-PT (parallel trends), TD-PT and NTD-PT are the assumptions of Sections 2 and 3 of the paper; TD-E-LOGS and TD-PR are those of the Proportional appendix. For TD_E_LOGS the counterfactual ratio uses δ̂APO×\hat\delta^{\times}_{APO}; the share_parenthood row of TD_E_LOGS uses ρ̂cf×\hat\rho^{\times}_{cf} in place of ρ̂cf\hat\rho_{cf}.

The standard errors of share_parenthood and share_other are not in the paper, which reports parenthood’s share as a point estimate (Section 4.2); the influence function in the table is the chain rule applied to s=(ρcf−ρobs)/(1−ρobs)s = (\rho_{cf} - \rho_{obs})/(1 - \rho_{obs}).

bias_bounds()

The bias-corrected conventional gap at an assumed fathers’ effect θ(m)\theta(m) (Proposition 2, in the form of the Estimation appendix), with Δ̂\hat\Delta the NTD rho_effect estimate: B̂(θ(m))=Δ̂δ̂APO(m)δ̂APO(f)(1+θ(m)), \hat B(\theta(m)) = \hat\Delta\,\frac{\hat\delta_{APO}(m)}{\hat\delta_{APO}(f)}\,\big(1 + \theta(m)\big), ψB=(1+θ(m))[δAPO(m)δAPO(f)ψΔ+ΔδAPO(f)ψδAPO(m)−ΔδAPO(m)δAPO(f)2ψδAPO(f)]. \psi_{B} = \big(1 + \theta(m)\big)\Big[\frac{\delta_{APO}(m)}{\delta_{APO}(f)}\psi_{\Delta} + \frac{\Delta}{\delta_{APO}(f)}\psi_{\delta_{APO}(m)} - \frac{\Delta\,\delta_{APO}(m)}{\delta_{APO}(f)^2}\psi_{\delta_{APO}(f)}\Big]. The estimator is in the paper; its influence function is not in the paper. The standard error scales with 1+θ(m)1 + \theta(m).

aggregate_estimands()

The aggregate estimators, their influence functions and standard errors are in Aggregation.

Where this lives in the code

quantity code
cell means and their IF; clustered variance R/utility.R: compute_mean_if(), se_cluster()
all rows of the table above R/single_treatment_group_analysis.R
aggregation R/aggregate_estimands.R
bias-corrected gap R/bias_bounds.R

Standard errors checked against a person-level (cluster) bootstrap in tests/testthat/: TD_E_LOGS and TD_PR rho_effect / gap_theta_pre, NTD share_parenthood, and bias_bounds(). TD_E_LOGS and TD_PR are also checked by Monte Carlo (dev/sims/td_sim_results.md in the source repository).