Panel.Estimand­Characterization.Staggered­TWFEDecomposition

The Goodman-Bacon decomposition: TWFE-DiD as a weighted average of 2x2 comparisons, with the weight formulas.

Support 20 core · 28 supporting · 5 submodules Support layer for the Goodman-Bacon decomposition: saturated cohort-period classes, cell-mass identities, orthogonality lemmas, residualization witnesses, and per-cell numerator and denominator formulas.
Finite­Panel 38 core · 4 supporting This file provides the finite cohort-period primitives for the Goodman-Bacon two-way fixed-effect decomposition. ★ Dtilde_eq

Goodman-Bacon Panel Algebra

This file provides the finite cohort-period primitives for the Goodman-Bacon two-way fixed-effect decomposition. It defines staggered adoption panels, absorbing treatment, residualized treatment, the TWFE coefficient, comparison windows, pairwise comparison contrasts, and the raw and normalized weights for treated-versus-never, early-versus-late, and late-versus-early comparisons.

inductive CompTag reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

The three-category comparison label classifies each admissible two-by-two comparison as a treated cohort against a never-treated cohort, an early-adopting cohort against a later-adopting cohort before the latter adopts, or a later-adopting cohort against an early-adopting cohort after the latter adopts.

Definition (Lean source)
CompTag :
Type
TN :
EL :
LE :
deriving DecidableEq
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CompTag · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:57
structure CohortPanel reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

A staggered-adoption cohort panel: a cell-statistics record carrying, per cohort, a population share, an adoption date — a finite period, or for the never-treated case, and the cohort-period factual outcome mean, subject to a positive number of periods, strictly positive cohort shares, and cohort shares summing to one.

Definition (Lean source)
𝒢 :
Type*
T :
Fintype 𝒢
Cohort population share `p_g`.
p :
𝒢 → ℝ
Adoption date `A_g ∈ 𝒯 ∪ {∞}`, encoded with `⊤ = ∞`.
A :
𝒢 → WithTop (Fin T)
Cohort-period factual outcome mean `Y_{gt}`.
Y :
𝒢 → Fin T → ℝ
The number of periods is positive.
T_pos :
0 < T
Cohort shares are strictly positive.
p_pos :
∀ g, 0 < p g
Cohort shares sum to one.
p_sum_one :
∑ g, p g = 1
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CohortPanel · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:64
def le reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate

For an adoption date and a panel period, the adopted-by-period condition holds exactly when the adoption date is no later than that period; a never-adopting cohort does not satisfy it.

Definition (Lean source)
T :
a :
t :
Fin T
le a t :
Prop
a ≤ (t : WithTop (Fin T))
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate.le · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:85
def lt reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate

For an adoption date and a panel period, the untreated-at-period condition holds exactly when the period precedes the adoption date, including every period for a never-adopting cohort.

Definition (Lean source)
T :
a :
t :
Fin T
lt a t :
Prop
(t : WithTop (Fin T)) < a
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate.lt · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:88
def isFin reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate

For an adoption date, the eventually-treated condition holds exactly when the date is a finite panel period rather than the never-adopting value.

Definition (Lean source)
T :
a :
isFin a :
Prop
a ≠ ⊤
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate.isFin · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:91
def isInf reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate

For an adoption date, the never-treated condition holds exactly when the date is the never-adopting value.

Definition (Lean source)
T :
a :
isInf a :
Prop
a = ⊤
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.AdoptionDate.isInf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:94
def D reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a cohort, and a period, the treatment indicator equals one if the cohort has adopted by that period and zero otherwise, and is therefore binary and absorbing.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
t :
Fin T
D P g t :
if AdoptionDate.le (P.A g) t then 1 else 0
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.D · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:102 · uses CohortPanel
def barD reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a cohort, the cohort treatment share is that cohort's treatment indicator averaged over all panel periods.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
barD P g :
(T : ℝ)⁻¹ * ∑ t, D P g t
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.barD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:108 · uses CohortPanel
def pCohort reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the overall treatment share is the sum of each cohort's population share times its average treatment indicator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
pCohort P :
∑ g, P.p g * barD P g
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.pCohort · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:112 · uses CohortPanel
def cohortWeights reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the cohort weight system assigns each cohort its population share and carries the panel's positivity and unit-sum conditions.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
cohortWeights P :
WeightedTwoWayPanel.UnitWeights 𝒢
⟨P.p, P.p_pos, P.p_sum_one⟩
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.cohortWeights · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:116 · uses CohortPanel , UnitWeights
def Dtilde reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a cohort, and a period, the residualized treatment is the treatment indicator minus its cohort mean and its cross-cohort period mean, plus the grand mean.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
t :
Fin T
Dtilde P g t :
WeightedTwoWayPanel.ddot (cohortWeights P) (D P) g t
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Dtilde · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:133 · uses CohortPanel
theorem Dtilde_eq reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a cohort-period cell, the double-demeaned residualized treatment Dtilde P g t equals the original Goodman-Bacon closed form: the raw treatment minus the cohort mean, minus the period cross-cohort mean, plus the grand mean.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
t :
Fin T
Dtilde P g t = D P g t - barD P g - (∑ g', P.p g' * D P g' t) + pCohort P
Proof (Lean source)
theorem Dtilde_eq (P : CohortPanel 𝒢 T) (g : 𝒢) (t : Fin T) : Dtilde P g t = D P g t - barD P g - (∑ g', P.p g' * D P g' t) + pCohort P := by unfold Dtilde WeightedTwoWayPanel.ddot rw [← barD_eq_unitMean P g, ← pCohort_eq_grandMean P] unfold WeightedTwoWayPanel.timeMean cohortWeights simp
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Dtilde_eq · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:138 · uses CohortPanel , D , Dtilde , barD , pCohort
def VD reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the residualized-treatment variance is the sum, over cohorts and periods, of the cohort share divided by the number of periods times squared residualized treatment.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
VD P :
∑ g, ∑ t, (P.p g / (T : ℝ)) * (Dtilde P g t)^2
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.VD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:149 · uses CohortPanel
def betaTWFE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the finite-cell population two-way-fixed-effects coefficient is the weighted covariance of residualized treatment and factual outcomes divided by residualized-treatment variance; it is defined even when that denominator is zero.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
betaTWFE P :
(∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t) / VD P
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.betaTWFE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:153 · uses CohortPanel
def Ybar reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a cohort, and a set of periods, the factual-outcome window mean is the average factual outcome for that cohort over the specified periods, and is defined as zero when the set is empty.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
S :
Ybar P g S :
(S.card : ℝ)⁻¹ * ∑ t ∈ S, P.Y g t
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Ybar · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:159 · uses CohortPanel
def S0_TN reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a cohort, the treated-versus-never untreated window is the set of all panel periods before that cohort's adoption date.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
S0_TN P g :
Finset.univ.filter (fun t => AdoptionDate.lt (P.A g) t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S0_TN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:166 · uses CohortPanel
def S1_TN reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a cohort, the treated-versus-never treated window is the set of all panel periods at or after that cohort's adoption date.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
S1_TN P g :
Finset.univ.filter (fun t => AdoptionDate.le (P.A g) t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S1_TN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:171 · uses CohortPanel
def S0_EL reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and an early-adopting cohort, the early-versus-late untreated window is the set of all periods before the early cohort's adoption date.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e :
𝒢
S0_EL P e :
Finset.univ.filter (fun t => AdoptionDate.lt (P.A e) t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S0_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:176 · uses CohortPanel
def S1_EL reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the early-versus-late treated window is the set of periods from the early cohort's adoption through the period before the late cohort's adoption.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
S1_EL P e ℓ :
Finset.univ.filter (fun t => AdoptionDate.le (P.A e) t ∧ AdoptionDate.lt (P.A ℓ) t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S1_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:181 · uses CohortPanel
def S0_LE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the late-versus-early early-treated window is the set of periods from the early cohort's adoption through the period before the late cohort's adoption.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
S0_LE P e ℓ :
S1_EL P e ℓ
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S0_LE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:186 · uses CohortPanel
def S1_LE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a late cohort, the late-versus-early both-treated window is the set of all periods at or after the late cohort's adoption date.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
:
𝒢
S1_LE P ℓ :
Finset.univ.filter (fun t => AdoptionDate.le (P.A ℓ) t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.S1_LE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:191 · uses CohortPanel
def Δ_TN reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a treated cohort, and a never-treated comparison cohort, the treated-versus-never two-by-two difference-in-differences contrast is the treated cohort's outcome change between its treated and untreated windows minus the comparison cohort's change over those same windows.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
Δ_TN P g u :
(Ybar P g (S1_TN P g) - Ybar P g (S0_TN P g))
- (Ybar P u (S1_TN P g) - Ybar P u (S0_TN P g))
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Δ_TN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:197 · uses CohortPanel
def Δ_EL reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the early-versus-late two-by-two difference-in-differences contrast is the early cohort's outcome change from its untreated to its treated-before-late window minus the late cohort's change over those same windows.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
Δ_EL P e ℓ :
(Ybar P e (S1_EL P e ℓ) - Ybar P e (S0_EL P e))
- (Ybar P ℓ (S1_EL P e ℓ) - Ybar P ℓ (S0_EL P e))
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Δ_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:202 · uses CohortPanel
def Δ_LE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the late-versus-early two-by-two difference-in-differences contrast is the late cohort's outcome change from the early-treated window to the both-treated window minus the early cohort's change over those same windows.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
Δ_LE P e ℓ :
(Ybar P ℓ (S1_LE P ℓ) - Ybar P ℓ (S0_LE P e ℓ))
- (Ybar P e (S1_LE P ℓ) - Ybar P e (S0_LE P e ℓ))
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Δ_LE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:207 · uses CohortPanel
def lambdaTN reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a treated cohort, and a never-treated cohort, the treated-versus-never raw weight is the product of their population shares and the treated cohort's average treatment indicator times one minus that indicator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
lambdaTN P g u :
P.p g * P.p u * (barD P g * (1 - barD P g))
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaTN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:214 · uses CohortPanel
def q reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the treatment-share gap is the early cohort's average treatment indicator minus the late cohort's average treatment indicator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
q P e ℓ :
barD P e - barD P ℓ
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.q · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:218 · uses CohortPanel
def mu reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the comparison splitting fraction is one minus the early cohort's treatment share divided by one minus their treatment-share gap, with the usual zero-denominator convention.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
mu P e ℓ :
(1 - barD P e) / (1 - q P e ℓ)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.mu · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:222 · uses CohortPanel
def lambdaEL reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the early-versus-late raw weight is the product of their shares, their treatment-share gap, one minus that gap, and the comparison splitting fraction.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
lambdaEL P e ℓ :
P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) * mu P e ℓ
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaEL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:226 · uses CohortPanel
def lambdaLE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the late-versus-early raw weight is the product of their shares, their treatment-share gap, one minus that gap, and one minus the comparison splitting fraction.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
lambdaLE P e ℓ :
P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) * (1 - mu P e ℓ)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaLE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:230 · uses CohortPanel
def Lambda reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the aggregate raw-weight denominator is the sum of treated-versus-never raw weights for finite-versus-never-treated pairs and the two timing-comparison raw weights for ordered finite adoption-date pairs.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
Lambda P :
(∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then lambdaTN P g u else 0)
+ (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ + lambdaLE P e ℓ else 0)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Lambda · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:235 · uses CohortPanel
def w_TN reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a treated cohort, and a never-treated cohort, the normalized treated-versus-never weight is its raw weight divided by the aggregate raw-weight denominator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
w_TN P g u :
lambdaTN P g u / Lambda P
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.w_TN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:242 · uses CohortPanel
def w_EL reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the normalized early-versus-late weight is its raw weight divided by the aggregate raw-weight denominator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
w_EL P e ℓ :
lambdaEL P e ℓ / Lambda P
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.w_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:246 · uses CohortPanel
def w_LE reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, an early cohort, and a late cohort, the normalized late-versus-early weight is its raw weight divided by the aggregate raw-weight denominator.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
e ℓ :
𝒢
w_LE P e ℓ :
lambdaLE P e ℓ / Lambda P
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.w_LE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:250 · uses CohortPanel
def admissible reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a tagged ordered cohort pair, the admissibility condition holds precisely when a treated-versus-never tag pairs an eventually treated cohort with a never-treated cohort, or either timing-comparison tag orders two finitely adopting cohorts by adoption date, and in every case both cohort shares are positive.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
k :
CompTag × 𝒢 × 𝒢
admissible P k :
Prop
match k.1 with | CompTag.TN => AdoptionDate.isFin (P.A k.2.1) ∧
AdoptionDate.isInf (P.A k.2.2) ∧
0 < P.p k.2.1 ∧
0 < P.p k.2.2 | CompTag.EL => P.A k.2.1 < P.A k.2.2 ∧
AdoptionDate.isFin (P.A k.2.2) ∧
0 < P.p k.2.1 ∧
0 < P.p k.2.2 | CompTag.LE => P.A k.2.1 < P.A k.2.2 ∧
AdoptionDate.isFin (P.A k.2.2) ∧
0 < P.p k.2.1 ∧
0 < P.p k.2.2
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.admissible · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:256 · uses CohortPanel , CompTag
def 𝒦 reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the comparison index set is the finite set of every tagged ordered cohort pair satisfying the admissibility condition.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
𝒦 P :
Finset (CompTag × 𝒢 × 𝒢)
(Finset.univ : Finset (CompTag × 𝒢 × 𝒢)).filter (fun k => admissible P k)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.𝒦 · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:270 · uses CohortPanel , CompTag
def weight reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a tagged ordered cohort pair, the unified normalized weight is the normalized weight associated with that pair's comparison tag when the pair is admissible, and zero otherwise.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
k :
CompTag × 𝒢 × 𝒢
weight P k :
if admissible P k then match k.1 with | CompTag.TN
=> w_TN P k.2.1 k.2.2 | CompTag.EL => w_EL P k.2.1 k.2.2 | CompTag.LE => w_LE P k.2.1 k.2.2 else 0
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.weight · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:275 · uses CohortPanel , CompTag
def contrast reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a tagged ordered cohort pair, the unified two-by-two contrast is the contrast associated with that pair's comparison tag when the pair is admissible, and zero otherwise.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
k :
CompTag × 𝒢 × 𝒢
contrast P k :
if admissible P k then match k.1 with | CompTag.TN
=> Δ_TN P k.2.1 k.2.2 | CompTag.EL => Δ_EL P k.2.1 k.2.2 | CompTag.LE => Δ_LE P k.2.1 k.2.2 else 0
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.contrast · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:285 · uses CohortPanel , CompTag
def lambdaWeight reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and a tagged ordered cohort pair, the unified raw weight is the raw weight associated with that pair's comparison tag when the pair is admissible, and zero otherwise.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
k :
CompTag × 𝒢 × 𝒢
lambdaWeight P k :
if admissible P k then match k.1 with | CompTag.TN
=> lambdaTN P k.2.1 k.2.2 | CompTag.EL => lambdaEL P k.2.1 k.2.2 | CompTag.LE => lambdaLE P k.2.1 k.2.2 else 0
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaWeight · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/FinitePanel.lean:295 · uses CohortPanel , CompTag
4 supporting declarations (lemmas, instances)
Causal 6 core · 9 supporting This file gives the causal layer of the Goodman-Bacon staggered-timing decomposition. ★ Δ_TN_eq_ATT★ Δ_EL_eq_ATT★ Δ_LE_eq_bad_comparison

Goodman-Bacon Causal Characterization

This file gives the causal layer of the Goodman-Bacon staggered-timing decomposition. Under two-state potential-outcome assumptions, consistency, no anticipation, and pairwise untreated parallel trends, it identifies the treated-versus-never and early-versus-late contrasts with window-specific average treatment effects and expresses the late-versus-early contrast with its bad-comparison adjustment.

def Ybar0 reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a never-treated potential-outcome schedule, a cohort, and a set of periods, the never-treated potential-outcome window mean is the average of that cohort's never-treated potential outcomes over the specified periods; it is defined as zero when the set is empty.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
Y0 :
𝒢 → Fin T → ℝ
g :
𝒢
S :
Ybar0 Y0 g S :
(S.card : ℝ)⁻¹ * ∑ t ∈ S, Y0 g t
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Ybar0 · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:96
def ATT_window reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For the never-treated potential-outcome schedule, the own-adoption potential-outcome schedule, a cohort, and a set of periods, the window-specific average treatment effect on the treated is the average over the specified periods of the own-adoption potential outcome minus the never-treated potential outcome for that cohort; it is defined as zero when the set is empty.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
Y0 Y1 :
𝒢 → Fin T → ℝ
g :
𝒢
S :
ATT_window Y0 Y1 g S :
(S.card : ℝ)⁻¹ * ∑ t ∈ S, (Y1 g t - Y0 g t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.ATT_window · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:100
structure CausalAssumptions reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Causal-side assumptions for the Goodman-Bacon decomposition (LaTeX ass:po-estimand-goodman-bacon-causal), given a cohort panel P and potential-outcome maps Y0 (the never-treated path) and Y1 (each cohort's own adoption-date path). It packages consistency on treated cells — the factual outcome equals the post-adoption potential outcome once the cohort has adopted, consistency on untreated cells — the factual outcome equals the never-treated potential outcome before adoption, no anticipation — the pre-adoption potential outcomes under the two paths coincide, and pairwise untreated parallel trends for the treated-versus-never comparison, the early-versus-late-before-late comparison, and the late-versus-early-after-early comparison.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
consistencyTreated :
∀ g t
if
AdoptionDate.le (P.A g) t
then
P.Y g t = Y1 g t

Consistency on treated cells: when A_g ≤ t, the factual outcome equals the post-adoption potential outcome.

consistencyUntreated :
∀ g t
if
AdoptionDate.lt (P.A g) t
then
P.Y g t = Y0 g t

Consistency on untreated cells: when t < A_g, the factual outcome equals the never-treated potential outcome.

noAnticipation :
∀ g t
if
AdoptionDate.lt (P.A g) t
then
Y1 g t = Y0 g t

No anticipation: pre-adoption potential outcomes coincide.

parallelTrends_TN :
∀ g u
if
AdoptionDate.isFin (P.A g)
and
AdoptionDate.isInf (P.A u)
then
Ybar0 Y0 g (S1_TN P g) - Ybar0 Y0 g (S0_TN P g)
= Ybar0 Y0 u (S1_TN P g) - Ybar0 Y0 u (S0_TN P g)

Pairwise untreated parallel trends for treated-vs-never (TN).

parallelTrends_EL :
∀ e ℓ
if
P.A e < P.A ℓ
and
AdoptionDate.isFin (P.A ℓ)
then
Ybar0 Y0 e (S1_EL P e ℓ) - Ybar0 Y0 e (S0_EL P e)
= Ybar0 Y0 ℓ (S1_EL P e ℓ) - Ybar0 Y0 ℓ (S0_EL P e)

Pairwise untreated parallel trends for early-vs-late before late (EL).

parallelTrends_LE :
∀ e ℓ
if
P.A e < P.A ℓ
and
AdoptionDate.isFin (P.A ℓ)
then
Ybar0 Y0 e (S1_LE P ℓ) - Ybar0 Y0 e (S0_LE P e ℓ)
= Ybar0 Y0 ℓ (S1_LE P ℓ) - Ybar0 Y0 ℓ (S0_LE P e ℓ)

Pairwise untreated parallel trends for late-vs-early after early (LE).

Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:105 · uses CohortPanel
theorem Δ_TN_eq_ATT reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Layer C corollary 1 — TN identifies ATT. Fix a cohort panel P and potential-outcome maps Y0 (never-treated path) and Y1 (own-adoption-date path), and assume consistency on treated and untreated cells, no anticipation, and pairwise untreated parallel trends across the three comparison types. For a treated cohort g whose adoption date is finite compared against a never-treated cohort u whose adoption date is infinite, the treated-versus-never 2x2 difference-in-differences contrast Δ_TN equals g's window-specific average treatment effect on the treated over its post-adoption window:

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
hA :
g u :
𝒢
h_g_fin :
AdoptionDate.isFin (P.A g)
h_u_inf :
AdoptionDate.isInf (P.A u)
Δ_TN P g u = ATT_window Y0 Y1 g (S1_TN P g)
Proof (Lean source)
theorem Δ_TN_eq_ATT (P : CohortPanel 𝒢 T) (Y0 Y1 : 𝒢 → Fin T → ℝ) (hA : CausalAssumptions P Y0 Y1) (g u : 𝒢) (h_g_fin : AdoptionDate.isFin (P.A g)) (h_u_inf : AdoptionDate.isInf (P.A u)) : Δ_TN P g u = ATT_window Y0 Y1 g (S1_TN P g) := by classical have h_treated : Ybar P g (S1_TN P g) = Ybar0 Y0 g (S1_TN P g) + ATT_window Y0 Y1 g (S1_TN P g) := by exact CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated hA.consistencyTreated g (S1_TN P g) (by intro t ht simpa [S1_TN, mem_filter] using ht) have h_g0 := CausalAssumptions.Ybar_eq_Ybar0_on_S0_TN hA.consistencyUntreated g have h_u1 := CausalAssumptions.Ybar_eq_Ybar0_of_inf hA.consistencyUntreated (S1_TN P g) (fun _ _ => CausalAssumptions.AdoptionDate.lt_of_isInf h_u_inf) have h_u0 := CausalAssumptions.Ybar_eq_Ybar0_of_inf hA.consistencyUntreated (S0_TN P g) (fun _ _ => CausalAssumptions.AdoptionDate.lt_of_isInf h_u_inf) have hPT := hA.parallelTrends_TN g u h_g_fin h_u_inf unfold Δ_TN rw [h_treated, h_g0, h_u1, h_u0] linarith
theorem Δ_EL_eq_ATT reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Layer C corollary 2 — EL identifies the early cohort's ATT. Fix a cohort panel P and potential-outcome maps Y0, Y1, and assume consistency on treated and untreated cells, no anticipation, and pairwise untreated parallel trends across the three comparison types. For an early cohort e whose adoption date strictly precedes that of a late cohort , with 's adoption date finite, the early-versus-late contrast Δ_EL equals e's window-specific average treatment effect on the treated over the window running from e's own adoption date up to 's adoption date:

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
hA :
e ℓ :
𝒢
h_lt :
P.A e < P.A ℓ
h_ℓ_fin :
AdoptionDate.isFin (P.A ℓ)
Δ_EL P e ℓ = ATT_window Y0 Y1 e (S1_EL P e ℓ)
Proof (Lean source)
theorem Δ_EL_eq_ATT (P : CohortPanel 𝒢 T) (Y0 Y1 : 𝒢 → Fin T → ℝ) (hA : CausalAssumptions P Y0 Y1) (e ℓ : 𝒢) (h_lt : P.A e < P.A ℓ) (h_ℓ_fin : AdoptionDate.isFin (P.A ℓ)) : Δ_EL P e ℓ = ATT_window Y0 Y1 e (S1_EL P e ℓ) := by classical have h_e1 : Ybar P e (S1_EL P e ℓ) = Ybar0 Y0 e (S1_EL P e ℓ) + ATT_window Y0 Y1 e (S1_EL P e ℓ) := by exact CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated hA.consistencyTreated e (S1_EL P e ℓ) (by intro t ht have htmem : AdoptionDate.le (P.A e) t ∧ AdoptionDate.lt (P.A ℓ) t := by simpa [S1_EL, mem_filter] using ht exact htmem.1) have h_e0 := CausalAssumptions.Ybar_eq_Ybar0_on_S0_EL hA.consistencyUntreated e have h_l1 := CausalAssumptions.Ybar_eq_Ybar0_late_on_S1_EL hA.consistencyUntreated e ℓ have h_l0 := CausalAssumptions.Ybar_eq_Ybar0_late_on_S0_EL hA.consistencyUntreated e ℓ h_lt have hPT := hA.parallelTrends_EL e ℓ h_lt h_ℓ_fin unfold Δ_EL rw [h_e1, h_e0, h_l1, h_l0] linarith
theorem Δ_LE_eq_bad_comparison reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Layer C corollary 3 — LE has a bad-comparison term. Fix a cohort panel P and potential-outcome maps Y0, Y1, and assume consistency on treated and untreated cells, no anticipation, and pairwise untreated parallel trends across the three comparison types. For an early cohort e whose adoption date strictly precedes that of a late cohort , with 's adoption date finite, the late-versus-early contrast Δ_LE equals 's window-specific average treatment effect on the treated over its post-adoption window, minus the "bad-comparison" gap between e's own treatment effects on the two comparison windows:

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
hA :
e ℓ :
𝒢
h_lt :
P.A e < P.A ℓ
h_ℓ_fin :
AdoptionDate.isFin (P.A ℓ)
Δ_LE P e ℓ
= ATT_window Y0 Y1 ℓ (S1_LE P ℓ)
- (ATT_window Y0 Y1 e (S1_LE P ℓ) - ATT_window Y0 Y1 e (S0_LE P e ℓ))
Proof (Lean source)
theorem Δ_LE_eq_bad_comparison (P : CohortPanel 𝒢 T) (Y0 Y1 : 𝒢 → Fin T → ℝ) (hA : CausalAssumptions P Y0 Y1) (e ℓ : 𝒢) (h_lt : P.A e < P.A ℓ) (h_ℓ_fin : AdoptionDate.isFin (P.A ℓ)) : Δ_LE P e ℓ = ATT_window Y0 Y1 ℓ (S1_LE P ℓ) - (ATT_window Y0 Y1 e (S1_LE P ℓ) - ATT_window Y0 Y1 e (S0_LE P e ℓ)) := by classical have h_l1 : Ybar P ℓ (S1_LE P ℓ) = Ybar0 Y0 ℓ (S1_LE P ℓ) + ATT_window Y0 Y1 ℓ (S1_LE P ℓ) := by exact CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated hA.consistencyTreated ℓ (S1_LE P ℓ) (by intro t ht simpa [S1_LE, mem_filter] using ht) have h_l0 := CausalAssumptions.Ybar_eq_Ybar0_late_on_S0_LE hA.consistencyUntreated e ℓ have h_e0 : Ybar P e (S0_LE P e ℓ) = Ybar0 Y0 e (S0_LE P e ℓ) + ATT_window Y0 Y1 e (S0_LE P e ℓ) := by exact CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated hA.consistencyTreated e (S0_LE P e ℓ) (by intro t ht have htmem : AdoptionDate.le (P.A e) t ∧ AdoptionDate.lt (P.A ℓ) t := by simpa [S0_LE, S1_EL, mem_filter] using ht exact htmem.1) have h_e1 : Ybar P e (S1_LE P ℓ) = Ybar0 Y0 e (S1_LE P ℓ) + ATT_window Y0 Y1 e (S1_LE P ℓ) := by exact CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated hA.consistencyTreated e (S1_LE P ℓ) (by intro t ht have hle : AdoptionDate.le (P.A ℓ) t := by simpa [S1_LE, mem_filter] using ht exact le_of_lt (lt_of_lt_of_le h_lt hle)) have hPT := hA.parallelTrends_LE e ℓ h_lt h_ℓ_fin unfold Δ_LE rw [h_l1, h_l0, h_e1, h_e0] linarith
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Δ_LE_eq_bad_comparison · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:383 · uses ATT_window , isFin , CausalAssumptions , CohortPanel , S0_LE , S1_LE , Δ_LE
9 supporting declarations (lemmas, instances)
  • not_le_of_lt theorem — Helper: AdoptionDate.lt (P.A g) t rules out AdoptionDate.le (P.A g) t.
    T :
    Fin T
    shared
    h :
    AdoptionDate.lt a t
    ¬ AdoptionDate.le a t
    Proof (Lean source)
    theorem AdoptionDate.not_le_of_lt {a : WithTop (Fin T)} {t : Fin T} (h : AdoptionDate.lt a t) : ¬ AdoptionDate.le a t := by intro hle exact lt_irrefl _ (lt_of_lt_of_le h hle)
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.AdoptionDate.not_le_of_lt · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:161
  • lt_of_isInf theorem — Helper: every period is strictly less than ⊤ in WithTop (Fin T).
    T :
    Fin T
    shared
    h :
    AdoptionDate.isInf a
    AdoptionDate.lt a t
    Proof (Lean source)
    theorem AdoptionDate.lt_of_isInf {a : WithTop (Fin T)} {t : Fin T} (h : AdoptionDate.isInf a) : AdoptionDate.lt a t := by unfold AdoptionDate.lt AdoptionDate.isInf at * rw [h] exact (WithTop.coe_lt_top _ : (t : WithTop (Fin T)) < ⊤)
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.AdoptionDate.lt_of_isInf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:167
  • Ybar_eq_Ybar0_on_S0_TN theorem — On the untreated window S0_TN P g = {t : t < A_g}, the factual Ybar of cohort g equals the never-treated Ybar0: by consistencyUntreated on each cell.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    g :
    𝒢
    Ybar P g (S0_TN P g) = Ybar0 Y0 g (S0_TN P g)
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_on_S0_TN (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) (g : 𝒢) : Ybar P g (S0_TN P g) = Ybar0 Y0 g (S0_TN P g) := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht have htlt : AdoptionDate.lt (P.A g) t := by simpa [S0_TN, mem_filter] using ht exact hConsistency g t htlt
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_on_S0_TN · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:175
  • Ybar_eq_Ybar0_of_inf theorem — On any window S where every period is untreated for cohort u, the factual Ybar equals the never-treated Ybar0.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    u :
    𝒢
    S :
    hS :
    ∀ t ∈ S, AdoptionDate.lt (P.A u) t
    Ybar P u S = Ybar0 Y0 u S
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_of_inf (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) {u : 𝒢} (S : Finset (Fin T)) (hS : ∀ t ∈ S, AdoptionDate.lt (P.A u) t) : Ybar P u S = Ybar0 Y0 u S := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht exact hConsistency u t (hS t ht)
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_of_inf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:191
  • Ybar_eq_Ybar0_add_ATT_of_treated theorem — On a window where every cell is treated for cohort g, the factual Ybar decomposes as the never-treated mean plus the window ATT.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.le (P.A g) t
    then
    P.Y g t = Y1 g t
    g :
    𝒢
    S :
    hS :
    ∀ t ∈ S, AdoptionDate.le (P.A g) t
    Ybar P g S = Ybar0 Y0 g S + ATT_window Y0 Y1 g S
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_add_ATT_of_treated (hConsistency : ∀ g t, AdoptionDate.le (P.A g) t → P.Y g t = Y1 g t) (g : 𝒢) (S : Finset (Fin T)) (hS : ∀ t ∈ S, AdoptionDate.le (P.A g) t) : Ybar P g S = Ybar0 Y0 g S + ATT_window Y0 Y1 g S := by classical unfold Ybar Ybar0 ATT_window rw [← mul_add] congr 1 calc ∑ t ∈ S, P.Y g t = ∑ t ∈ S, Y1 g t := by refine Finset.sum_congr rfl ?_ intro t ht exact hConsistency g t (hS t ht) _ = ∑ t ∈ S, (Y0 g t + (Y1 g t - Y0 g t)) := by refine Finset.sum_congr rfl ?_ intro t _ ring _ = ∑ t ∈ S, Y0 g t + ∑ t ∈ S, (Y1 g t - Y0 g t) := by exact Finset.sum_add_distrib
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_add_ATT_of_treated · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:206
  • Ybar_eq_Ybar0_on_S0_EL theorem — On the early-cohort untreated window S0_EL P e = {t : t < A_e}, the factual Ybar of cohort e equals the never-treated Ybar0.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    e :
    𝒢
    Ybar P e (S0_EL P e) = Ybar0 Y0 e (S0_EL P e)
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_on_S0_EL (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) (e : 𝒢) : Ybar P e (S0_EL P e) = Ybar0 Y0 e (S0_EL P e) := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht have htlt : AdoptionDate.lt (P.A e) t := by simpa [S0_EL, mem_filter] using ht exact hConsistency e t htlt
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_on_S0_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:230
  • Ybar_eq_Ybar0_late_on_S1_EL theorem — The late-cohort factual Ybar on S1_EL P e ℓ = {A_e ≤ t < A_ℓ} equals the never-treated Ybar0: each cell satisfies t < A_ℓ.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    e ℓ :
    𝒢
    Ybar P ℓ (S1_EL P e ℓ) = Ybar0 Y0 ℓ (S1_EL P e ℓ)
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_late_on_S1_EL (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) (e ℓ : 𝒢) : Ybar P ℓ (S1_EL P e ℓ) = Ybar0 Y0 ℓ (S1_EL P e ℓ) := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht have htmem : AdoptionDate.le (P.A e) t ∧ AdoptionDate.lt (P.A ℓ) t := by simpa [S1_EL, mem_filter] using ht exact hConsistency ℓ t htmem.2
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_late_on_S1_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:245
  • Ybar_eq_Ybar0_late_on_S0_EL theorem — The late-cohort factual Ybar on S0_EL P e = {t : t < A_e} equals the never-treated Ybar0 when A_e < A_ℓ.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    e ℓ :
    𝒢
    h_lt :
    P.A e < P.A ℓ
    Ybar P ℓ (S0_EL P e) = Ybar0 Y0 ℓ (S0_EL P e)
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_late_on_S0_EL (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) (e ℓ : 𝒢) (h_lt : P.A e < P.A ℓ) : Ybar P ℓ (S0_EL P e) = Ybar0 Y0 ℓ (S0_EL P e) := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht have htlt : (t : WithTop (Fin T)) < P.A e := by have h0 : AdoptionDate.lt (P.A e) t := by simpa [S0_EL, mem_filter] using ht exact h0 exact hConsistency ℓ t (by simpa [AdoptionDate.lt] using lt_trans htlt h_lt)
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_late_on_S0_EL · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:260
  • Ybar_eq_Ybar0_late_on_S0_LE theorem — The late-cohort factual Ybar on S0_LE P e ℓ = {A_e ≤ t < A_ℓ} equals the never-treated Ybar0.
    𝒢 :
    Type u_1
    shared
    T :
    𝒢 → Fin T → ℝ
    shared
    hConsistency :
    ∀ g t
    if
    AdoptionDate.lt (P.A g) t
    then
    P.Y g t = Y0 g t
    e ℓ :
    𝒢
    Ybar P ℓ (S0_LE P e ℓ) = Ybar0 Y0 ℓ (S0_LE P e ℓ)
    Proof (Lean source)
    theorem Ybar_eq_Ybar0_late_on_S0_LE (hConsistency : ∀ g t, AdoptionDate.lt (P.A g) t → P.Y g t = Y0 g t) (e ℓ : 𝒢) : Ybar P ℓ (S0_LE P e ℓ) = Ybar0 Y0 ℓ (S0_LE P e ℓ) := by classical unfold Ybar Ybar0 congr 1 refine Finset.sum_congr rfl ?_ intro t ht have htmem : AdoptionDate.le (P.A e) t ∧ AdoptionDate.lt (P.A ℓ) t := by simpa [S0_LE, S1_EL, mem_filter] using ht exact hConsistency ℓ t htmem.2
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.CausalAssumptions.Ybar_eq_Ybar0_late_on_S0_LE · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Causal.lean:279
Algebraic­Decomposition 3 core · 11 supporting This file establishes the finite staggered-adoption Goodman-Bacon algebraic decomposition of a two-way fixed effects coefficient into admissible two-group comparisons. ★ weights_nonneg★ weights_sum_one★ twfe_eq_weighted_avg

Goodman-Bacon Decomposition

This file establishes the finite staggered-adoption Goodman-Bacon algebraic decomposition of a two-way fixed effects coefficient into admissible two-group comparisons. It proves nonnegativity of the raw comparison weights, the denominator and numerator identities, normalization of the weights under positive residualized-treatment variance, and the corresponding weighted-average identity.

theorem weights_nonneg reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Prop A5.1 (weights_nonneg). For a cohort panel and any comparison-type index, the raw Goodman-Bacon comparison weight is nonnegative.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
k :
CompTag × 𝒢 × 𝒢
0 ≤ lambdaWeight P k
Proof (Lean source)
theorem weights_nonneg (P : CohortPanel 𝒢 T) (k : CompTag × 𝒢 × 𝒢) : 0 ≤ lambdaWeight P k := by classical unfold lambdaWeight have hTpos : 0 < (T : ℝ) := by exact_mod_cast P.T_pos have hTnonneg : 0 ≤ (T : ℝ) := le_of_lt hTpos have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (Nat.ne_of_gt P.T_pos) have hbar_nonneg : ∀ g : 𝒢, 0 ≤ barD P g := by intro g unfold barD have hsum_nonneg : 0 ≤ ∑ t : Fin T, D P g t := by refine Finset.sum_nonneg' ?_ intro t by_cases hD : AdoptionDate.le (P.A g) t · simp [D, hD] · simp [D, hD] simpa using (mul_nonneg (inv_nonneg.mpr hTnonneg) hsum_nonneg) have hbar_le_one : ∀ g : 𝒢, barD P g ≤ 1 := by intro g unfold barD have hsum_le : ∑ t : Fin T, D P g t ≤ (T : ℝ) := by have hsum_le' : (∑ t : Fin T, D P g t) ≤ (∑ t : Fin T, (1 : ℝ)) := by refine Finset.sum_le_sum ?_ intro t ht by_cases hD : AdoptionDate.le (P.A g) t · simp [D, hD] · simp [D, hD] simpa using hsum_le' have hsum_le'' : (∑ t, D P g t) ≤ (T : ℝ) := by simpa using hsum_le have htmp : (T : ℝ)⁻¹ * (∑ t, D P g t) ≤ (T : ℝ)⁻¹ * (T : ℝ) := mul_le_mul_of_nonneg_left hsum_le'' (inv_nonneg.mpr hTnonneg) simpa [barD, inv_mul_cancel₀ hTne] using htmp by_cases h : admissible P k · simp only [h, if_true] rcases k with ⟨tag, g, u⟩ cases tag with | TN => rcases h with ⟨_, _, hpg, hpu⟩ have hmul : 0 ≤ (P.p g * P.p u) * (barD P g * (1 - barD P g)) := by exact mul_nonneg (mul_nonneg (le_of_lt hpg) (le_of_lt hpu)) (mul_nonneg (hbar_nonneg g) (sub_nonneg.mpr (hbar_le_one g))) simpa [lambdaTN, mul_assoc, mul_left_comm, mul_comm] using hmul | EL => rcases h with ⟨hlt, _, hpg, hpu⟩ have hbar_mono : barD P u ≤ barD P g := by unfold barD have hsum_le : (∑ t : Fin T, D P u t) ≤ (∑ t : Fin T, D P g t) := by refine Finset.sum_le_sum ?_ intro t ht by_cases htu : AdoptionDate.le (P.A u) t · have htg : AdoptionDate.le (P.A g) t := le_of_lt (lt_of_lt_of_le hlt htu) simp [D, htu, htg] · by_cases htg : AdoptionDate.le (P.A g) t · simp [D, htu, htg] · simp [D, htu, htg] have hsum_le' : (∑ t : Fin T, D P u t) ≤ (∑ t : Fin T, D P g t) := by simpa using hsum_le exact mul_le_mul_of_nonneg_left hsum_le' (inv_nonneg.mpr hTnonneg) have hq_nonneg : 0 ≤ q P g u := by unfold q exact sub_nonneg.mpr hbar_mono have hq_le_barD : q P g u ≤ barD P g := by unfold q nlinarith [hbar_mono, hbar_nonneg u] have hq_le_one : q P g u ≤ 1 := le_trans hq_le_barD (hbar_le_one g) have h1mq_nonneg : 0 ≤ 1 - q P g u := sub_nonneg.mpr hq_le_one have hmu_nonneg : 0 ≤ mu P g u := by unfold mu exact div_nonneg (sub_nonneg.mpr (hbar_le_one g)) h1mq_nonneg have hnum_le_den : 1 - barD P g ≤ 1 - q P g u := by have hlu_nonneg : 0 ≤ barD P u := hbar_nonneg u unfold q linarith have hmu_le_one : mu P g u ≤ 1 := by by_cases hden : 1 - q P g u = 0 · have hqeq : q P g u = 1 := by linarith simp [mu, hqeq] · have hden_pos : 0 < 1 - q P g u := lt_of_le_of_ne h1mq_nonneg (Ne.symm hden) have hdiv : (1 - barD P g) / (1 - q P g u) ≤ 1 := (div_le_one₀ hden_pos).2 hnum_le_den simpa [mu] using hdiv have h1m_nonneg : 0 ≤ 1 - mu P g u := sub_nonneg.mpr hmu_le_one have hmul : 0 ≤ P.p g * P.p u * (q P g u * (1 - q P g u) * mu P g u) := by have hmul1 : 0 ≤ P.p g * P.p u := mul_nonneg (le_of_lt hpg) (le_of_lt hpu) have hmul2 : 0 ≤ q P g u * (1 - q P g u) := mul_nonneg hq_nonneg h1mq_nonneg have hmul3 : 0 ≤ q P g u * (1 - q P g u) * mu P g u := mul_nonneg hmul2 hmu_nonneg exact mul_nonneg hmul1 hmul3 simpa [lambdaEL, mul_assoc, mul_left_comm, mul_comm] using hmul | LE => rcases h with ⟨hlt, _, hpg, hpu⟩ have hbar_mono : barD P u ≤ barD P g := by unfold barD have hsum_le : (∑ t : Fin T, D P u t) ≤ (∑ t : Fin T, D P g t) := by refine Finset.sum_le_sum ?_ intro t ht by_cases htu : AdoptionDate.le (P.A u) t · have htg : AdoptionDate.le (P.A g) t := le_of_lt (lt_of_lt_of_le hlt htu) simp [D, htu, htg] · by_cases htg : AdoptionDate.le (P.A g) t · simp [D, htu, htg] · simp [D, htu, htg] have hsum_le' : (∑ t : Fin T, D P u t) ≤ (∑ t : Fin T, D P g t) := by simpa using hsum_le exact mul_le_mul_of_nonneg_left hsum_le' (inv_nonneg.mpr hTnonneg) have hq_nonneg : 0 ≤ q P g u := by unfold q exact sub_nonneg.mpr hbar_mono have hq_le_barD : q P g u ≤ barD P g := by unfold q nlinarith [hbar_mono, hbar_nonneg u] have hq_le_one : q P g u ≤ 1 := le_trans hq_le_barD (hbar_le_one g) have h1mq_nonneg : 0 ≤ 1 - q P g u := sub_nonneg.mpr hq_le_one have hmu_nonneg : 0 ≤ mu P g u := by unfold mu exact div_nonneg (sub_nonneg.mpr (hbar_le_one g)) h1mq_nonneg have hnum_le_den : 1 - barD P g ≤ 1 - q P g u := by have hlu_nonneg : 0 ≤ barD P u := hbar_nonneg u unfold q linarith have hmu_le_one : mu P g u ≤ 1 := by by_cases hden : 1 - q P g u = 0 · have hqeq : q P g u = 1 := by linarith simp [mu, hqeq] · have hden_pos : 0 < 1 - q P g u := lt_of_le_of_ne h1mq_nonneg (Ne.symm hden) have hdiv : (1 - barD P g) / (1 - q P g u) ≤ 1 := by exact (div_le_one₀ hden_pos).2 hnum_le_den simpa [mu] using hdiv have h1m_nonneg : 0 ≤ 1 - mu P g u := sub_nonneg.mpr hmu_le_one have hmul : 0 ≤ P.p g * P.p u * (q P g u * (1 - q P g u) * (1 - mu P g u)) := by have hmul1 : 0 ≤ P.p g * P.p u := mul_nonneg (le_of_lt hpg) (le_of_lt hpu) have hmul2 : 0 ≤ q P g u * (1 - q P g u) := mul_nonneg hq_nonneg h1mq_nonneg have hmul3 : 0 ≤ q P g u * (1 - q P g u) * (1 - mu P g u) := mul_nonneg hmul2 h1m_nonneg exact mul_nonneg hmul1 hmul3 simpa [lambdaLE, mul_assoc, mul_left_comm, mul_comm] using hmul · simp [h]
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.weights_nonneg · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:57 · uses CohortPanel , CompTag , lambdaWeight
theorem weights_sum_one reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Prop A5.4 (weights_sum_one). For a finite Goodman–Bacon cohort panel P, if the residualized-treatment variance VD P is strictly positive, then the normalized comparison weights sum to one over all admissible 2×2 comparisons: Σ_{k ∈ 𝒦 P} weight P k = 1.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
hVD_pos :
0 < VD P
∑ k ∈ 𝒦 P, weight P k = 1
Proof (Lean source)
theorem weights_sum_one (P : CohortPanel 𝒢 T) (hVD_pos : 0 < VD P) : ∑ k ∈ 𝒦 P, weight P k = 1 := by classical have hL_ne : Lambda P ≠ 0 := by rw [raw_weight_sum_eq_VD P] exact ne_of_gt hVD_pos have hsum_lambda : ∑ k ∈ 𝒦 P, lambdaWeight P k = Lambda P := by exact sum_lambdaWeight_eq_Lambda P calc ∑ k ∈ 𝒦 P, weight P k = ∑ k ∈ 𝒦 P, lambdaWeight P k / Lambda P := by refine Finset.sum_congr rfl ?_ intro k hk have hk' : admissible P k := by simpa [𝒦] using hk rcases k with ⟨tag, pair⟩ rcases pair with ⟨g, u⟩ cases tag <;> simp [weight, lambdaWeight, w_TN, w_EL, w_LE, hk'] _ = (∑ k ∈ 𝒦 P, lambdaWeight P k) / Lambda P := by simp [div_eq_mul_inv, Finset.mul_sum, mul_comm] _ = Lambda P / Lambda P := by rw [hsum_lambda] _ = 1 := by exact div_self hL_ne
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.weights_sum_one · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:638 · uses CohortPanel , CompTag , VD , weight , 𝒦
theorem twfe_eq_weighted_avg reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Theorem A5.5 (twfe_eq_weighted_avg, thm:po-estimand-goodman-bacon-decomposition). For a cohort panel, the two-way fixed-effects (TWFE) coefficient, under the totalized zero-variance convention, equals the weighted sum of admissible two-by-two DID contrasts across comparison groups.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrast P k
Proof (Lean source)
theorem twfe_eq_weighted_avg (P : CohortPanel 𝒢 T) : betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrast P k := twfe_eq_weighted_avg_core P
11 supporting declarations (lemmas, instances)
  • barD_eq_zero_of_isInf lemma — A never-treated cohort has zero average treatment over the panel.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g :
    𝒢
    hg :
    AdoptionDate.isInf (P.A g)
    barD P g = 0
    Proof (Lean source)
    lemma barD_eq_zero_of_isInf (P : CohortPanel 𝒢 T) {g : 𝒢} (hg : AdoptionDate.isInf (P.A g)) : barD P g = 0 := by unfold barD D AdoptionDate.isInf AdoptionDate.le at * simp [hg]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.barD_eq_zero_of_isInf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:202
  • lambdaTN_eq_gap_of_isInf lemma — When one cohort is never treated, its raw comparison weight with another cohort equals the product of their cohort shares, the gap in their average treatment rates, and one minus that gap.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g u :
    𝒢
    hu :
    AdoptionDate.isInf (P.A u)
    lambdaTN P g u = P.p g * P.p u * q P g u * (1 - q P g u)
    Proof (Lean source)
    lemma lambdaTN_eq_gap_of_isInf (P : CohortPanel 𝒢 T) {g u : 𝒢} (hu : AdoptionDate.isInf (P.A u)) : lambdaTN P g u = P.p g * P.p u * q P g u * (1 - q P g u) := by unfold lambdaTN q rw [barD_eq_zero_of_isInf P hu] ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaTN_eq_gap_of_isInf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:209
  • lambdaEL_add_lambdaLE_eq_gap lemma — The two ordered raw comparison weights between two cohorts sum to the product of their cohort shares, the gap in their average treatment rates, and one minus that gap.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    e ℓ :
    𝒢
    lambdaEL P e ℓ + lambdaLE P e ℓ = P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ)
    Proof (Lean source)
    lemma lambdaEL_add_lambdaLE_eq_gap (P : CohortPanel 𝒢 T) (e ℓ : 𝒢) : lambdaEL P e ℓ + lambdaLE P e ℓ = P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) := by unfold lambdaEL lambdaLE ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.lambdaEL_add_lambdaLE_eq_gap · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:219
  • Lambda_eq_gap_sums lemma — The raw denominator of the staggered-adoption two-way fixed-effects decomposition equals the sum of treated-versus-never comparison terms and ordered early-versus-late comparison terms.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then P.p g * P.p u * q P g u * (1 - q P g u) else 0)
    + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) else 0)
    Proof (Lean source)
    lemma Lambda_eq_gap_sums (P : CohortPanel 𝒢 T) : Lambda P = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then P.p g * P.p u * q P g u * (1 - q P g u) else 0) + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) else 0) := by unfold Lambda congr 1 · refine Finset.sum_congr rfl ?_ intro g _hg refine Finset.sum_congr rfl ?_ intro u _hu by_cases h : AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) · simp [h, lambdaTN_eq_gap_of_isInf P h.2] · simp [h] · refine Finset.sum_congr rfl ?_ intro e _he refine Finset.sum_congr rfl ?_ intro ℓ _hℓ by_cases h : P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) · simp [h, lambdaEL_add_lambdaLE_eq_gap P e ℓ] · simp [h]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Lambda_eq_gap_sums · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:229
  • D_eq_of_A_eq lemma — Cohorts that share the same adoption date have identical treatment status in every time period.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g u :
    𝒢
    hA :
    P.A g = P.A u
    t :
    Fin T
    D P g t = D P u t
    Proof (Lean source)
    lemma D_eq_of_A_eq (P : CohortPanel 𝒢 T) {g u : 𝒢} (hA : P.A g = P.A u) (t : Fin T) : D P g t = D P u t := by unfold D rw [hA]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.D_eq_of_A_eq · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:255
  • adoption_pair_sum_decomp lemma — When a pairwise cohort contribution is zero for cohorts sharing an adoption date, its total over all cohort pairs decomposes into the four possible ordered timing comparisons.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    f :
    𝒢 → 𝒢 → ℝ
    hzero :
    ∀ g u
    if
    P.A g = P.A u
    then
    f g u = 0
    (∑ g, ∑ u, f g u)
    = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then f g u else 0)
    + (∑ g, ∑ u, if AdoptionDate.isFin (P.A u) ∧ AdoptionDate.isInf (P.A g) then f g u else 0)
    + (∑ g, ∑ u, if P.A g < P.A u ∧ AdoptionDate.isFin (P.A u) then f g u else 0)
    + (∑ g, ∑ u, if P.A u < P.A g ∧ AdoptionDate.isFin (P.A g) then f g u else 0)
    Proof (Lean source)
    lemma adoption_pair_sum_decomp (P : CohortPanel 𝒢 T) (f : 𝒢 → 𝒢 → ℝ) (hzero : ∀ g u, P.A g = P.A u → f g u = 0) : (∑ g, ∑ u, f g u) = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then f g u else 0) + (∑ g, ∑ u, if AdoptionDate.isFin (P.A u) ∧ AdoptionDate.isInf (P.A g) then f g u else 0) + (∑ g, ∑ u, if P.A g < P.A u ∧ AdoptionDate.isFin (P.A u) then f g u else 0) + (∑ g, ∑ u, if P.A u < P.A g ∧ AdoptionDate.isFin (P.A g) then f g u else 0) := by calc (∑ g, ∑ u, f g u) = ∑ g, ∑ u, ((if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then f g u else 0) + (if AdoptionDate.isFin (P.A u) ∧ AdoptionDate.isInf (P.A g) then f g u else 0) + (if P.A g < P.A u ∧ AdoptionDate.isFin (P.A u) then f g u else 0) + (if P.A u < P.A g ∧ AdoptionDate.isFin (P.A g) then f g u else 0)) := by refine Finset.sum_congr rfl ?_ intro g _hg refine Finset.sum_congr rfl ?_ intro u _hu exact adoption_pair_pointwise P f hzero g u _ = _ := by simp [Finset.sum_add_distrib, add_assoc]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.adoption_pair_sum_decomp · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:372
  • gap_sums_eq_VD lemma — The total of cohort-share products times each pair's treatment-rate gap and one minus that gap, over treated-versus-never and ordered early-versus-later pairs, equals the residualized treatment variance.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then P.p g * P.p u * q P g u * (1 - q P g u) else 0)
    + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) else 0)
    = VD P
    Proof (Lean source)
    lemma gap_sums_eq_VD (P : CohortPanel 𝒢 T) : (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then P.p g * P.p u * q P g u * (1 - q P g u) else 0) + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) else 0) = VD P := by -- Remaining denominator algebra: expand `VD`, use `P.p_sum_one`, and group -- the pairwise variance of monotone adoption indicators by adoption-date -- order. This is the finite-sum manipulation described in the NL A5.2 doc. rw [VD_eq_pairwise_centeredD P] rw [adoption_pair_sum_grouped P (vdPairContribution P) (fun g u hA => vdPairContribution_eq_zero_of_A_eq P hA)] congr 1 · refine Finset.sum_congr rfl ?_ intro g _hg refine Finset.sum_congr rfl ?_ intro u _hu by_cases h : AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) · simp [h, TN_pair_vd_contribution_eq_gap P h.2] · simp [h] · refine Finset.sum_congr rfl ?_ intro e _he refine Finset.sum_congr rfl ?_ intro ℓ _hℓ by_cases h : P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) · simp [h, TT_pair_vd_contribution_eq_gap P h.1] · simp [h]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.gap_sums_eq_VD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:483
  • raw_weight_sum_eq_VD theorem — Prop A5.2 (raw_weight_sum_eq_VD). The aggregate raw-weight denominator equals the residualized treatment variance: Λ P = V_D P. Key denominator identity in thm:po-estimand-goodman-bacon-decomposition.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    Lambda P = VD P
    Proof (Lean source)
    theorem raw_weight_sum_eq_VD (P : CohortPanel 𝒢 T) : Lambda P = VD P := by rw [Lambda_eq_gap_sums] exact gap_sums_eq_VD P
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.raw_weight_sum_eq_VD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:514
  • twfe_numerator_eq_lambda_delta_sum theorem — Prop A5.3 (twfe_numerator_eq_lambda_delta_sum). The TWFE numerator decomposes by unordered cohort pairs into raw-weight times 2x2 DID contrast contributions.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    (∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t)
    = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then lambdaTN P g u * Δ_TN P g u else 0)
    + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ else 0)
    Proof (Lean source)
    theorem twfe_numerator_eq_lambda_delta_sum (P : CohortPanel 𝒢 T) : (∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t) = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then lambdaTN P g u * Δ_TN P g u else 0) + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ else 0) := by rw [twfe_numerator_eq_pairwise_centeredD_Y P] rw [adoption_pair_sum_grouped P (numPairContribution P) (fun g u hA => numPairContribution_eq_zero_of_A_eq P hA)] congr 1 · refine Finset.sum_congr rfl ?_ intro g _hg refine Finset.sum_congr rfl ?_ intro u _hu by_cases h : AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) · simp [h, TN_pair_contribution_eq_lambda_delta P h.1 h.2] · simp [h] · refine Finset.sum_congr rfl ?_ intro e _he refine Finset.sum_congr rfl ?_ intro ℓ _hℓ by_cases h : P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) · simp [h, TT_pair_contribution_eq_lambda_delta_sum P h.1 h.2] · simp [h]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.twfe_numerator_eq_lambda_delta_sum · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:524
  • sum_lambdaWeight_eq_Lambda lemma — Across all admissible comparison types and cohort pairs, the raw comparison weights sum to the aggregate normalizing denominator.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    ∑ k ∈ 𝒦 P, lambdaWeight P k = Lambda P
    Proof (Lean source)
    lemma sum_lambdaWeight_eq_Lambda (P : CohortPanel 𝒢 T) : ∑ k ∈ 𝒦 P, lambdaWeight P k = Lambda P := by classical rw [show (∑ k ∈ 𝒦 P, lambdaWeight P k) = ∑ k, if admissible P k then lambdaWeight P k else 0 by simp [𝒦, Finset.sum_filter]] rw [Fintype.sum_prod_type] rw [sum_compTag] simp only [lambdaWeight, admissible, P.p_pos, true_and] simp_rw [if_dup] simp_rw [Fintype.sum_prod_type] simp only [and_true] have hELLE : (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ else 0) + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaLE P e ℓ else 0) = ∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ + lambdaLE P e ℓ else 0 := by rw [← Finset.sum_add_distrib] refine Finset.sum_congr rfl ?_ intro e he rw [← Finset.sum_add_distrib] refine Finset.sum_congr rfl ?_ intro ℓ hℓ by_cases h : P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) <;> simp [h] unfold Lambda rw [← hELLE] rw [add_assoc]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.sum_lambdaWeight_eq_Lambda · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:570
  • twfe_eq_weighted_avg_core theorem — The positivity-free algebraic core of the Goodman-Bacon decomposition: the totalized TWFE ratio equals the totalized weighted sum of admissible two-by-two DID contrasts, including in zero-variance cases.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrast P k
    Proof (Lean source)
    theorem twfe_eq_weighted_avg_core (P : CohortPanel 𝒢 T) : betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrast P k := by classical have hnum := twfe_numerator_eq_lambda_delta_sum P have hsum : ∑ k ∈ 𝒦 P, lambdaWeight P k * contrast P k = (∑ g, ∑ u, if AdoptionDate.isFin (P.A g) ∧ AdoptionDate.isInf (P.A u) then lambdaTN P g u * Δ_TN P g u else 0) + (∑ e, ∑ ℓ, if P.A e < P.A ℓ ∧ AdoptionDate.isFin (P.A ℓ) then lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ else 0) := sum_lambdaWeight_mul_contrast_eq P have hweighted : ∑ k ∈ 𝒦 P, weight P k * contrast P k = (∑ k ∈ 𝒦 P, lambdaWeight P k * contrast P k) / Lambda P := by rw [Finset.sum_div] refine Finset.sum_congr rfl ?_ intro k hk have hk' : admissible P k := by simpa [𝒦] using hk rcases k with ⟨tag, pair⟩ rcases pair with ⟨g, u⟩ cases tag <;> simp [weight, lambdaWeight, w_TN, w_EL, w_LE, hk', div_eq_mul_inv, mul_left_comm, mul_comm] calc betaTWFE P = ((∑ k ∈ 𝒦 P, lambdaWeight P k * contrast P k) / Lambda P) := by unfold betaTWFE rw [hnum] rw [← hsum] rw [← raw_weight_sum_eq_VD P] _ = ∑ k ∈ 𝒦 P, weight P k * contrast P k := by rw [hweighted]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.twfe_eq_weighted_avg_core · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/AlgebraicDecomposition.lean:664
Causal­Decomposition 2 core · 1 supporting This file composes the algebraic TWFE totalized weighted-sum identity with the causal window-ATT corollaries, expressing the two-way fixed-effect coefficient as a sum of normalized comparison weights times potential-outc ★ twfe_po_decomposition

Goodman-Bacon fused causal decomposition

This file composes the algebraic TWFE totalized weighted-sum identity with the causal window-ATT corollaries, expressing the two-way fixed-effect coefficient as a sum of normalized comparison weights times potential-outcome window contrasts, with the late-versus-early bad-comparison term made explicit. A weighted-average interpretation requires the separate positive-variance condition used by weights_sum_one.

def contrastCausal reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a finite collection of cohorts whose members can be compared for equality, a natural-number panel length, a cohort panel, two potential-outcome paths, respectively under no treatment and under treatment at the cohort's own adoption date, and a labelled ordered pair of cohorts, the causal two-by-two contrast is zero when that comparison is inadmissible; otherwise, it is the relevant window average treatment effect for a treated-versus-never-treated or early-versus-late comparison, and for a late-versus-early comparison it is the late cohort's window average treatment effect minus the early cohort's corresponding treated-period effect net of its pre-period effect.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
k :
CompTag × 𝒢 × 𝒢
contrastCausal P Y0 Y1 k :
if admissible P k then match k.1 with | CompTag.TN
=> ATT_window Y0 Y1 k.2.1 (S1_TN P k.2.1) | CompTag.EL => ATT_window Y0 Y1 k.2.1 (S1_EL P k.2.1 k.2.2) | CompTag.LE => ATT_window Y0 Y1 k.2.2 (S1_LE P k.2.2)
- (ATT_window Y0 Y1 k.2.1 (S1_LE P k.2.2) - ATT_window Y0 Y1 k.2.1 (S0_LE P k.2.1 k.2.2)) else 0
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.contrastCausal · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/CausalDecomposition.lean:47 · uses CohortPanel , CompTag
theorem twfe_po_decomposition reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

Fused causal Goodman-Bacon decomposition. Fix a cohort panel P and potential-outcome maps Y0 (never-treated path) and Y1 (own-adoption-date path). Assume consistency on treated and untreated cells, no anticipation, and pairwise untreated parallel trends across the treated-versus-never, early-versus-late, and late-versus-early comparison types; then the two-way fixed-effects coefficient betaTWFE P equals the sum, over admissible pairwise comparisons, of each comparison's Goodman-Bacon weight times its potential-outcome window contrast — the treated-versus-never and early-versus-late window-specific ATTs, or the late-versus-early bad-comparison adjustment.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
Y0 Y1 :
𝒢 → Fin T → ℝ
hA :
betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrastCausal P Y0 Y1 k
Proof (Lean source)
theorem twfe_po_decomposition (P : CohortPanel 𝒢 T) (Y0 Y1 : 𝒢 → Fin T → ℝ) (hA : CausalAssumptions P Y0 Y1) : betaTWFE P = ∑ k ∈ 𝒦 P, weight P k * contrastCausal P Y0 Y1 k := by rw [twfe_eq_weighted_avg_core P] refine Finset.sum_congr rfl ?_ intro k hk have hk' : admissible P k := by simpa [𝒦] using hk rw [contrast_eq_contrastCausal P Y0 Y1 hA hk']
1 supporting declaration (lemmas, instances)
Pairwise 5 core · 13 supporting This file reduces Goodman-Bacon denominator and numerator terms to ordered-pair centered-treatment contributions. ★ VD_eq_pairwise_centeredD★ TN_pair_contribution_eq_lambda_delta

Goodman-Bacon Pairwise Algebra

This file reduces Goodman-Bacon denominator and numerator terms to ordered-pair centered-treatment contributions. It is the algebraic bridge between generic finite weighted covariance identities and the adoption-window case analysis that produces the three comparison types in the decomposition.

def centeredD reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, a cohort, and a period, the cohort-demeaned treatment path is that cohort's treatment indicator in the period minus its average treatment indicator across all periods.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g :
𝒢
t :
Fin T
centeredD P g t :
D P g t - barD P g
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.centeredD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:119 · uses CohortPanel
def vdPairContribution reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and two cohorts, the ordered-pair contribution to residualized-treatment variance is one half of their share product divided by the number of periods, multiplied by the sum of squared differences between their cohort-demeaned treatment paths.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
vdPairContribution P g u :
(P.p g * P.p u / (2 * (T : ℝ))) * ∑ t, (centeredD P g t - centeredD P u t)^2
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.vdPairContribution · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:123 · uses CohortPanel
def numPairContribution reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel and two cohorts, the ordered-pair contribution to the two-way-fixed-effects numerator is one half of their share product divided by the number of periods, multiplied by the sum of the product of their demeaned-treatment difference and factual-outcome difference.

Definition (Lean source)
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
numPairContribution P g u :
(P.p g * P.p u / (2 * (T : ℝ))) * ∑ t, (centeredD P g t - centeredD P u t) * (P.Y g t - P.Y u t)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.numPairContribution · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:133 · uses CohortPanel
lemma VD_eq_pairwise_centeredD reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

For a cohort panel, the residualized-treatment variance VD P equals the sum, over all ordered pairs of cohorts, of their pairwise centered-treatment contribution vdPairContribution P g u.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
VD P = ∑ g, ∑ u, vdPairContribution P g u
Proof (Lean source)
lemma VD_eq_pairwise_centeredD (P : CohortPanel 𝒢 T) : VD P = ∑ g, ∑ u, vdPairContribution P g u := by classical calc VD P = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * (Dtilde P g t)^2 := by unfold VD exact sum_weight_over_T_commute P (fun g t => (Dtilde P g t)^2) _ = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * (centeredD P g t - ∑ h, P.p h * centeredD P h t)^2 := by congr 1 refine Finset.sum_congr rfl ?_ intro t _ht refine Finset.sum_congr rfl ?_ intro g _hg rw [Dtilde_eq_centeredD_sub_weighted_mean] _ = (T : ℝ)⁻¹ * ∑ t, ((1 / 2) * ∑ g, ∑ u, P.p g * P.p u * (centeredD P g t - centeredD P u t)^2) := by congr 1 refine Finset.sum_congr rfl ?_ intro t _ht exact weighted_center_var (fun g => P.p g) (fun g => centeredD P g t) P.p_sum_one (by norm_num) _ = ∑ g, ∑ u, vdPairContribution P g u := by unfold vdPairContribution exact pairwise_sum_normalize P (fun g u t => (centeredD P g t - centeredD P u t)^2)
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.VD_eq_pairwise_centeredD · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:384 · uses CohortPanel , VD , vdPairContribution
lemma TN_pair_contribution_eq_lambda_delta reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

TN numerator pair. For a treated cohort g with finite adoption date and a never-treated cohort u with infinite adoption date, the sum of the two ordered pairwise-covariance contributions between g and u in the finite cohort panel P equals the product of the TN comparison weight and the treated-versus-never contrast, λ_TN P g u · Δ_TN P g u.

Formal statement
𝒢 :
Type u_1
shared
T :
shared
P :
g u :
𝒢
hg :
AdoptionDate.isFin (P.A g)
hu :
AdoptionDate.isInf (P.A u)
Proof (Lean source)
lemma TN_pair_contribution_eq_lambda_delta (P : CohortPanel 𝒢 T) {g u : 𝒢} (hg : AdoptionDate.isFin (P.A g)) (hu : AdoptionDate.isInf (P.A u)) : numPairContribution P g u + numPairContribution P u g = lambdaTN P g u * Δ_TN P g u := by rw [numPairContribution_add_swap] have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt P.T_pos) have hcov := TN_time_cov_eq_lambda_delta_core P hg hu calc (P.p g * P.p u / (T : ℝ)) * ∑ t, (centeredD P g t - centeredD P u t) * (P.Y g t - P.Y u t) = P.p g * P.p u * ((T : ℝ)⁻¹ * ∑ t, (centeredD P g t - centeredD P u t) * (P.Y g t - P.Y u t)) := by field_simp [hTne] _ = lambdaTN P g u * Δ_TN P g u := by rw [hcov] unfold lambdaTN ring
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.TN_pair_contribution_eq_lambda_delta · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:1003 · uses isFin , isInf , CohortPanel , lambdaTN , numPairContribution , Δ_TN
13 supporting declarations (lemmas, instances)
  • weighted_center_cov_uncentered_right lemma — For a finite collection with weights summing to one, the weighted sum of deviations of one quantity from its weighted mean times another quantity equals one half of the weighted sum of pairwise differences in the two quantities.
    ι :
    Type*
    p x y :
    ι → ℝ
    hp :
    ∑ i, p i = 1
    ∑ i, p i * (x i - ∑ j, p j * x j) * y i
    = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j)
    Proof (Lean source)
    lemma weighted_center_cov_uncentered_right {ι : Type*} [Fintype ι] (p x y : ι → ℝ) (hp : ∑ i, p i = 1) : ∑ i, p i * (x i - ∑ j, p j * x j) * y i = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j) := by classical let mx := ∑ j, p j * x j let my := ∑ j, p j * y j have hzero : ∑ i, p i * (x i - mx) = 0 := by calc ∑ i, p i * (x i - mx) = (∑ i, p i * x i) - ∑ i, p i * mx := by simp [mul_sub, Finset.sum_sub_distrib] _ = mx - (∑ i, p i) * mx := by simp [Finset.sum_mul, mx] _ = 0 := by rw [hp] ring have hmy : ∑ i, p i * (x i - mx) * my = 0 := by calc ∑ i, p i * (x i - mx) * my = (∑ i, p i * (x i - mx)) * my := by rw [Finset.sum_mul] _ = 0 := by rw [hzero] ring have hcenter : ∑ i, p i * (x i - mx) * y i = ∑ i, p i * (x i - mx) * (y i - my) := by calc ∑ i, p i * (x i - mx) * y i = ∑ i, (p i * (x i - mx) * (y i - my) + p i * (x i - mx) * my) := by refine Finset.sum_congr rfl ?_ intro i _hi ring _ = ∑ i, p i * (x i - mx) * (y i - my) + ∑ i, p i * (x i - mx) * my := by rw [Finset.sum_add_distrib] _ = ∑ i, p i * (x i - mx) * (y i - my) := by rw [hmy] ring calc ∑ i, p i * (x i - ∑ j, p j * x j) * y i = ∑ i, p i * (x i - mx) * y i := by rfl _ = ∑ i, p i * (x i - mx) * (y i - my) := hcenter _ = ∑ i, p i * (x i - ∑ j, p j * x j) * (y i - ∑ j, p j * y j) := by rfl _ = (1 / 2) * ∑ i, ∑ j, p i * p j * (x i - x j) * (y i - y j) := weighted_center_cov p x y hp (by norm_num)
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.weighted_center_cov_uncentered_right · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:40
  • sum_weight_over_T_commute lemma — In a finite cohort panel, a cohort-weighted sum over cohorts and periods with equal period weight equals the average over periods of the corresponding cohort-weighted sums.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    f :
    𝒢 → Fin T → ℝ
    (∑ g, ∑ t, (P.p g / (T : ℝ)) * f g t) = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * f g t
    Proof (Lean source)
    lemma sum_weight_over_T_commute (P : CohortPanel 𝒢 T) (f : 𝒢 → Fin T → ℝ) : (∑ g, ∑ t, (P.p g / (T : ℝ)) * f g t) = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * f g t := by classical rw [Finset.sum_comm] simp [div_eq_mul_inv, Finset.mul_sum, mul_left_comm, mul_comm]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.sum_weight_over_T_commute · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:88
  • pairwise_sum_normalize lemma — In a finite cohort panel, averaging half the ordered-pair weighted total at each period equals the ordered-pair weighted total of the time sums with the same normalization.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    f :
    𝒢 → 𝒢 → Fin T → ℝ
    (T : ℝ)⁻¹ * ∑ t, ((1 / 2) * ∑ g, ∑ u, P.p g * P.p u * f g u t)
    = ∑ g, ∑ u, (P.p g * P.p u / (2 * (T : ℝ))) * ∑ t, f g u t
    Proof (Lean source)
    lemma pairwise_sum_normalize (P : CohortPanel 𝒢 T) (f : 𝒢 → 𝒢 → Fin T → ℝ) : (T : ℝ)⁻¹ * ∑ t, ((1 / 2) * ∑ g, ∑ u, P.p g * P.p u * f g u t) = ∑ g, ∑ u, (P.p g * P.p u / (2 * (T : ℝ))) * ∑ t, f g u t := by classical calc (T : ℝ)⁻¹ * ∑ t, ((1 / 2) * ∑ g, ∑ u, P.p g * P.p u * f g u t) = (T : ℝ)⁻¹ * ∑ t, ∑ g, ∑ u, (1 / 2) * (P.p g * P.p u * f g u t) := by simp [Finset.mul_sum] _ = (T : ℝ)⁻¹ * ∑ g, ∑ u, ∑ t, (1 / 2) * (P.p g * P.p u * f g u t) := by congr 1 rw [Finset.sum_comm] refine Finset.sum_congr rfl ?_ intro g _hg rw [Finset.sum_comm] _ = ∑ g, ∑ u, (P.p g * P.p u / (2 * (T : ℝ))) * ∑ t, f g u t := by simp [div_eq_mul_inv, Finset.mul_sum, Finset.sum_mul, mul_assoc, mul_left_comm, mul_comm]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.pairwise_sum_normalize · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:99
  • D_eq_zero_of_isInf lemma — In a cohort panel, a cohort that is never treated has a zero treatment indicator in every period.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    u :
    𝒢
    hu :
    AdoptionDate.isInf (P.A u)
    t :
    Fin T
    D P u t = 0
    Proof (Lean source)
    lemma D_eq_zero_of_isInf (P : CohortPanel 𝒢 T) {u : 𝒢} (hu : AdoptionDate.isInf (P.A u)) (t : Fin T) : D P u t = 0 := by classical unfold D rw [show P.A u = ⊤ from hu] simp [AdoptionDate.le]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.D_eq_zero_of_isInf · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:142
  • D_sq_eq_D lemma — In a cohort panel, the binary treatment indicator for any cohort and time period equals its own square.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g :
    𝒢
    t :
    Fin T
    D P g t ^ 2 = D P g t
    Proof (Lean source)
    lemma D_sq_eq_D (P : CohortPanel 𝒢 T) (g : 𝒢) (t : Fin T) : D P g t ^ 2 = D P g t := by unfold D by_cases h : AdoptionDate.le (P.A g) t <;> simp [h]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.D_sq_eq_D · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:160
  • binary_time_variance lemma — For a binary quantity observed over the panel's time periods, its average squared deviation from its time mean equals that mean times one minus that mean.
    T :
    shared
    hT_pos :
    0 < T
    x :
    Fin T → ℝ
    hx :
    ∀ t, x t ^ 2 = x t
    (T : ℝ)⁻¹ * ∑ t, (x t - ((T : ℝ)⁻¹ * ∑ t, x t)) ^ 2
    = ((T : ℝ)⁻¹ * ∑ t, x t) * (1 - ((T : ℝ)⁻¹ * ∑ t, x t))
    Proof (Lean source)
    lemma binary_time_variance (hT_pos : 0 < T) (x : Fin T → ℝ) (hx : ∀ t, x t ^ 2 = x t) : (T : ℝ)⁻¹ * ∑ t, (x t - ((T : ℝ)⁻¹ * ∑ t, x t)) ^ 2 = ((T : ℝ)⁻¹ * ∑ t, x t) * (1 - ((T : ℝ)⁻¹ * ∑ t, x t)) := by classical let m : ℝ := (T : ℝ)⁻¹ * ∑ t, x t have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt hT_pos) have hsum_sq : ∑ t, x t ^ 2 = ∑ t, x t := by exact Finset.sum_congr rfl (by intro t _ht; exact hx t) have hsum_expand : ∑ t, (x t ^ 2 - 2 * m * x t + m ^ 2) = ∑ t, x t - 2 * m * ∑ t, x t + (T : ℝ) * m ^ 2 := by calc ∑ t, (x t ^ 2 - 2 * m * x t + m ^ 2) = ∑ t, x t ^ 2 - ∑ t, 2 * m * x t + ∑ _t : Fin T, m ^ 2 := by simp [Finset.sum_sub_distrib, Finset.sum_add_distrib] _ = ∑ t, x t - 2 * m * ∑ t, x t + (T : ℝ) * m ^ 2 := by rw [hsum_sq] simp [Finset.mul_sum, Fintype.card_fin] calc (T : ℝ)⁻¹ * ∑ t, (x t - ((T : ℝ)⁻¹ * ∑ t, x t)) ^ 2 = (T : ℝ)⁻¹ * ∑ t, (x t ^ 2 - 2 * m * x t + m ^ 2) := by congr 1 refine Finset.sum_congr rfl ?_ intro t _ht simp [m] ring _ = ((T : ℝ)⁻¹ * ∑ t, x t) * (1 - ((T : ℝ)⁻¹ * ∑ t, x t)) := by rw [hsum_expand] simp [m] field_simp [hTne] ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.binary_time_variance · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:168
  • binary_time_cov_filter_mean lemma — For an indicator of a nonempty set of periods, the time-average product of its centered value and another quantity equals its variance times the difference between the selected-period and unselected-period averages of that quantity.
    T :
    shared
    hT_pos :
    0 < T
    p :
    Fin T → Prop
    z :
    Fin T → ℝ
    hcard1 :
    ((Finset.univ.filter p).card : ℝ) ≠ 0
    (T : ℝ)⁻¹ * ∑ t, ((if p t then (1 : ℝ) else 0) - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * z t
    = ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0)) * (1 - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * (((Finset.univ.filter p).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter p), z t) - ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter (fun t => ¬ p t)), z t))
    Proof (Lean source)
    lemma binary_time_cov_filter_mean (hT_pos : 0 < T) (p : Fin T → Prop) [DecidablePred p] (z : Fin T → ℝ) (hcard1 : ((Finset.univ.filter p).card : ℝ) ≠ 0) : (T : ℝ)⁻¹ * ∑ t, ((if p t then (1 : ℝ) else 0) - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * z t = ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0)) * (1 - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * (((Finset.univ.filter p).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter p), z t) - ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter (fun t => ¬ p t)), z t)) := by classical have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt hT_pos) let A : ℝ := ((Finset.univ.filter p).card : ℝ) let B : ℝ := ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ) let Z1 : ℝ := ∑ t ∈ (Finset.univ.filter p), z t let Z0 : ℝ := ∑ t ∈ (Finset.univ.filter (fun t => ¬ p t)), z t have hA : A ≠ 0 := by simpa [A] using hcard1 have hsum_if : (∑ t, (if p t then (1 : ℝ) else 0)) = A := by simp [A] have hsum_if_z : (∑ t, (if p t then (1 : ℝ) else 0) * z t) = Z1 := by simp [Z1, Finset.sum_filter] have hsum_z : (∑ t, z t) = Z1 + Z0 := by simp [Z1, Z0, Finset.sum_filter] rw [← Finset.sum_add_distrib] refine Finset.sum_congr rfl ?_ intro t _ by_cases ht : p t <;> simp [ht] have hcard_total : A + B = (T : ℝ) := by have hnat : (Finset.univ.filter p).card + (Finset.univ.filter (fun t => ¬ p t)).card = T := by calc (Finset.univ.filter p).card + (Finset.univ.filter (fun t => ¬ p t)).card = ((Finset.univ.filter p) ∪ (Finset.univ.filter (fun t => ¬ p t))).card := by rw [Finset.card_union_of_disjoint] simp [Finset.disjoint_left] _ = T := by have hunion : (Finset.univ.filter p) ∪ (Finset.univ.filter (fun t => ¬ p t)) = (Finset.univ : Finset (Fin T)) := by ext t simp [em] simp [hunion] simpa [A, B] using (show (((Finset.univ.filter p).card : ℝ) + ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ) = (T : ℝ)) by exact_mod_cast hnat) have hmain : (T : ℝ)⁻¹ * (Z1 - ((T : ℝ)⁻¹ * A) * (Z1 + Z0)) = ((T : ℝ)⁻¹ * A) * (1 - ((T : ℝ)⁻¹ * A)) * (A⁻¹ * Z1 - B⁻¹ * Z0) := by by_cases hB : B = 0 · have hZT0 : Z0 = 0 := by have hempty : Finset.univ.filter (fun t => ¬ p t) = ∅ := by apply Finset.card_eq_zero.mp have hB' : ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ) = 0 := by simpa [B] using hB exact_mod_cast hB' simp [Z0, hempty] have hAeq : A = (T : ℝ) := by linarith rw [hZT0, hAeq] field_simp [hTne] ring · have hABne : A + B ≠ 0 := by rw [hcard_total] exact hTne rw [← hcard_total] field_simp [hA, hB, hABne] ring calc (T : ℝ)⁻¹ * ∑ t, ((if p t then (1 : ℝ) else 0) - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * z t = (T : ℝ)⁻¹ * (Z1 - ((T : ℝ)⁻¹ * A) * (Z1 + Z0)) := by rw [hsum_if] calc (T : ℝ)⁻¹ * ∑ t, ((if p t then (1 : ℝ) else 0) - (T : ℝ)⁻¹ * A) * z t = (T : ℝ)⁻¹ * (∑ t, (if p t then (1 : ℝ) else 0) * z t - ∑ t, ((T : ℝ)⁻¹ * A) * z t) := by congr 1 rw [← Finset.sum_sub_distrib] refine Finset.sum_congr rfl ?_ intro t _ ring _ = (T : ℝ)⁻¹ * (Z1 - ((T : ℝ)⁻¹ * A) * (Z1 + Z0)) := by rw [hsum_if_z, ← Finset.mul_sum, hsum_z] _ = ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0)) * (1 - ((T : ℝ)⁻¹ * ∑ t, (if p t then (1 : ℝ) else 0))) * (((Finset.univ.filter p).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter p), z t) - ((Finset.univ.filter (fun t => ¬ p t)).card : ℝ)⁻¹ * (∑ t ∈ (Finset.univ.filter (fun t => ¬ p t)), z t)) := by rw [hmain, hsum_if]
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.binary_time_cov_filter_mean · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:206
  • Dtilde_eq_centeredD_sub_weighted_mean lemma — The explicit double-demeaning formula for Dtilde is the weighted centering, across cohorts, of the cohort-demeaned treatment path.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g :
    𝒢
    t :
    Fin T
    Dtilde P g t = centeredD P g t - ∑ h, P.p h * centeredD P h t
    Proof (Lean source)
    lemma Dtilde_eq_centeredD_sub_weighted_mean (P : CohortPanel 𝒢 T) (g : 𝒢) (t : Fin T) : Dtilde P g t = centeredD P g t - ∑ h, P.p h * centeredD P h t := by rw [weighted_centeredD_mean P t] rw [Dtilde_eq] unfold centeredD ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.Dtilde_eq_centeredD_sub_weighted_mean · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:374
  • twfe_numerator_eq_pairwise_centeredD_Y lemma — Pairwise representation of the TWFE numerator.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    (∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t)
    = ∑ g, ∑ u, numPairContribution P g u
    Proof (Lean source)
    lemma twfe_numerator_eq_pairwise_centeredD_Y (P : CohortPanel 𝒢 T) : (∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t) = ∑ g, ∑ u, numPairContribution P g u := by classical calc (∑ g, ∑ t, (P.p g / (T : ℝ)) * Dtilde P g t * P.Y g t) = ∑ g, ∑ t, (P.p g / (T : ℝ)) * (Dtilde P g t * P.Y g t) := by refine Finset.sum_congr rfl ?_ intro g _hg refine Finset.sum_congr rfl ?_ intro t _ht ring _ = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * (Dtilde P g t * P.Y g t) := by exact sum_weight_over_T_commute P (fun g t => Dtilde P g t * P.Y g t) _ = (T : ℝ)⁻¹ * ∑ t, ∑ g, P.p g * (centeredD P g t - ∑ h, P.p h * centeredD P h t) * P.Y g t := by congr 1 refine Finset.sum_congr rfl ?_ intro t _ht refine Finset.sum_congr rfl ?_ intro g _hg rw [Dtilde_eq_centeredD_sub_weighted_mean] ring _ = (T : ℝ)⁻¹ * ∑ t, ((1 / 2) * ∑ g, ∑ u, P.p g * P.p u * (centeredD P g t - centeredD P u t) * (P.Y g t - P.Y u t)) := by congr 1 refine Finset.sum_congr rfl ?_ intro t _ht exact weighted_center_cov_uncentered_right (fun g => P.p g) (fun g => centeredD P g t) (fun g => P.Y g t) P.p_sum_one _ = ∑ g, ∑ u, numPairContribution P g u := by unfold numPairContribution simpa [mul_assoc] using pairwise_sum_normalize P (fun g u t => (centeredD P g t - centeredD P u t) * (P.Y g t - P.Y u t))
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.twfe_numerator_eq_pairwise_centeredD_Y · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:419
  • disjoint_union_mean_eq_card_weighted_mean lemma — When two finite sets are disjoint and the second is nonempty, the mean of a quantity over their union is the cardinality-weighted combination of its means over the two sets.
    α :
    Type*
    A B :
    z :
    α → ℝ
    hdisj :
    hB :
    ((B.card : ℝ) ≠ 0)
    (((A ∪ B).card : ℝ)⁻¹ * ∑ t ∈ A ∪ B, z t)
    = ((A.card : ℝ) / ((A ∪ B).card : ℝ)) * ((A.card : ℝ)⁻¹ * ∑ t ∈ A, z t)
    + (1 - ((A.card : ℝ) / ((A ∪ B).card : ℝ))) * ((B.card : ℝ)⁻¹ * ∑ t ∈ B, z t)
    Proof (Lean source)
    lemma disjoint_union_mean_eq_card_weighted_mean {α : Type*} [DecidableEq α] (A B : Finset α) (z : α → ℝ) (hdisj : Disjoint A B) (hB : ((B.card : ℝ) ≠ 0)) : (((A ∪ B).card : ℝ)⁻¹ * ∑ t ∈ A ∪ B, z t) = ((A.card : ℝ) / ((A ∪ B).card : ℝ)) * ((A.card : ℝ)⁻¹ * ∑ t ∈ A, z t) + (1 - ((A.card : ℝ) / ((A ∪ B).card : ℝ))) * ((B.card : ℝ)⁻¹ * ∑ t ∈ B, z t) := by classical let a : ℝ := A.card let b : ℝ := B.card let ZA : ℝ := ∑ t ∈ A, z t let ZB : ℝ := ∑ t ∈ B, z t have hsum : ∑ t ∈ A ∪ B, z t = ZA + ZB := by simp [ZA, ZB, Finset.sum_union hdisj] have hcard : ((A ∪ B).card : ℝ) = a + b := by have hnat : (A ∪ B).card = A.card + B.card := Finset.card_union_of_disjoint hdisj simp [a, b, hnat] have hb : b ≠ 0 := by simpa [b] using hB have hbpos : 0 < b := by have hBnat : B.card ≠ 0 := by exact_mod_cast hB dsimp [b] exact_mod_cast (Nat.pos_of_ne_zero hBnat) have hab : a + b ≠ 0 := by intro h have ha_nonneg : 0 ≤ a := by dsimp [a] exact_mod_cast (zero_le A.card) linarith by_cases ha : a = 0 · have hAempty : A = ∅ := by apply Finset.card_eq_zero.mp have : (A.card : ℝ) = 0 := by simpa [a] using ha exact Nat.cast_eq_zero.mp this have hZA : ZA = 0 := by simp [ZA, hAempty] rw [hsum, hcard, hZA, ha] simp [hAempty] field_simp [hb] ring · have haA : ((A.card : ℝ) ≠ 0) := by simpa [a] using ha have hAB : ((A.card : ℝ) + (B.card : ℝ)) ≠ 0 := by simpa [a, b] using hab rw [hsum, hcard] field_simp [haA, hB, hAB] simp [a, b, ZA, ZB] ring_nf
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.disjoint_union_mean_eq_card_weighted_mean · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:600
  • TN_pair_vd_contribution_eq_gap lemma — TN denominator pair: combining the two ordered pairwise-variance contributions gives the treated-vs-never raw denominator factor.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    g u :
    𝒢
    hu :
    AdoptionDate.isInf (P.A u)
    = P.p g * P.p u * q P g u * (1 - q P g u)
    Proof (Lean source)
    lemma TN_pair_vd_contribution_eq_gap (P : CohortPanel 𝒢 T) {g u : 𝒢} (hu : AdoptionDate.isInf (P.A u)) : vdPairContribution P g u + vdPairContribution P u g = P.p g * P.p u * q P g u * (1 - q P g u) := by rw [vdPairContribution_add_swap] have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt P.T_pos) have hvar := TN_time_variance_eq_gap P (g := g) hu calc (P.p g * P.p u / (T : ℝ)) * ∑ t, (centeredD P g t - centeredD P u t)^2 = P.p g * P.p u * ((T : ℝ)⁻¹ * ∑ t, (centeredD P g t - centeredD P u t)^2) := by field_simp [hTne] _ = P.p g * P.p u * q P g u * (1 - q P g u) := by rw [hvar] ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.TN_pair_vd_contribution_eq_gap · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:961
  • TT_pair_vd_contribution_eq_gap lemma — Treated-treated denominator pair: combining the two ordered pairwise-variance contributions gives the timing-pair raw denominator factor.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    e ℓ :
    𝒢
    hord :
    P.A e < P.A ℓ
    = P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ)
    Proof (Lean source)
    lemma TT_pair_vd_contribution_eq_gap (P : CohortPanel 𝒢 T) {e ℓ : 𝒢} (hord : P.A e < P.A ℓ) : vdPairContribution P e ℓ + vdPairContribution P ℓ e = P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) := by rw [vdPairContribution_add_swap] have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt P.T_pos) have hvar := TT_time_variance_eq_gap P hord calc (P.p e * P.p ℓ / (T : ℝ)) * ∑ t, (centeredD P e t - centeredD P ℓ t)^2 = P.p e * P.p ℓ * ((T : ℝ)⁻¹ * ∑ t, (centeredD P e t - centeredD P ℓ t)^2) := by field_simp [hTne] _ = P.p e * P.p ℓ * q P e ℓ * (1 - q P e ℓ) := by rw [hvar] ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.TT_pair_vd_contribution_eq_gap · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:982
  • TT_pair_contribution_eq_lambda_delta_sum lemma — Treated-treated numerator pair: combining the two ordered pairwise-covariance contributions splits into the EL and LE comparison windows.
    𝒢 :
    Type u_1
    shared
    T :
    shared
    P :
    e ℓ :
    𝒢
    hord :
    P.A e < P.A ℓ
    hℓ :
    AdoptionDate.isFin (P.A ℓ)
    = lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ
    Proof (Lean source)
    lemma TT_pair_contribution_eq_lambda_delta_sum (P : CohortPanel 𝒢 T) {e ℓ : 𝒢} (hord : P.A e < P.A ℓ) (hℓ : AdoptionDate.isFin (P.A ℓ)) : numPairContribution P e ℓ + numPairContribution P ℓ e = lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ := by rw [numPairContribution_add_swap] have hTne : (T : ℝ) ≠ 0 := by exact_mod_cast (ne_of_gt P.T_pos) have hcov := TT_time_cov_eq_lambda_delta_core P hord hℓ calc (P.p e * P.p ℓ / (T : ℝ)) * ∑ t, (centeredD P e t - centeredD P ℓ t) * (P.Y e t - P.Y ℓ t) = P.p e * P.p ℓ * ((T : ℝ)⁻¹ * ∑ t, (centeredD P e t - centeredD P ℓ t) * (P.Y e t - P.Y ℓ t)) := by field_simp [hTne] _ = lambdaEL P e ℓ * Δ_EL P e ℓ + lambdaLE P e ℓ * Δ_LE P e ℓ := by rw [hcov] unfold lambdaEL lambdaLE ring
    Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition.TT_pair_contribution_eq_lambda_delta_sum · Causalean/Panel/EstimandCharacterization/StaggeredTWFEDecomposition/Pairwise.lean:1029
Population­Bridge 3 core · 0 supporting This file states the public bridge from a probability-space panel model to the finite Goodman-Bacon cohort-period algebra. ★ bridge_Dtilde_sq_eq_VD★ bridge_VD_pos_iff_Dtilde_sq_pos★ bridge_finite_residualized_eq_twfe

Goodman-Bacon Measure-Theoretic Bridge

This file states the public bridge from a probability-space panel model to the finite Goodman-Bacon cohort-period algebra. It relates residualized-treatment integrals to the finite-panel denominator and numerator, allowing the abstract residualized coefficient to be read as the finite-cell TWFE coefficient under the balanced cohort-period law.

theorem bridge_Dtilde_sq_eq_VD reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

On a probability space carrying cohort label G, period label T_rv, treatment D, and outcome Y, assume D is binary almost everywhere, there is at least one time period, every cohort has strictly positive population mass, the cohort masses sum to one, each cohort's mass is split evenly across periods (a balanced panel law), on each cohort-period cell D is almost-everywhere equal to its own cell mean (cell-measurability of D), and the population per-cell residualized treatment panelDtilde agrees with the finite-panel residualized treatment Dtilde. Then the population second moment of the residualized-treatment witness — the FWL denominator ∫ Vtilde² dμ — equals the finite-cell Goodman-Bacon denominator VD of the induced finite panel.

Formal statement
Ω :
Type u_1
shared
𝒢 :
Type u_2
shared
T :
shared
D Y :
Ω → ℝ
G :
Ω → 𝒢
T_rv :
Ω → Fin T
A :
𝒢 → WithTop (Fin T)
G_meas :
T_meas :
D_meas :
D_binary :
∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1
B_balanced :
hT_pos :
0 < T
hp_pos :
∀ g, 0 < cohortMass μ G g
hp_sum :
∑ g, cohortMass μ G g = 1
hLaw :
∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)
hD_cell :
∀ g t,
∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω
= (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t
hDtilde_eq :
∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t
(∫ ω, (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω * (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω ∂μ)
= VD (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum)
Proof (Lean source)
theorem bridge_Dtilde_sq_eq_VD (μ : Measure Ω) [IsProbabilityMeasure μ] (D Y : Ω → ℝ) (G : Ω → 𝒢) (T_rv : Ω → Fin T) (A : 𝒢 → WithTop (Fin T)) (G_meas : Measurable G) (T_meas : Measurable T_rv) (D_meas : Measurable D) (D_binary : ∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1) (B_balanced : IsBalancedPanelLaw μ G T_rv) (hT_pos : 0 < T) (hp_pos : ∀ g, 0 < cohortMass μ G g) (hp_sum : ∑ g, cohortMass μ G g = 1) (hLaw : ∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)) (hD_cell : ∀ g t, ∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω = (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t) (hDtilde_eq : ∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t) : (∫ ω, (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω * (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω ∂μ) = VD (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) := by let wD := residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced let P := panelOf μ Y G T_rv A hT_pos hp_pos hp_sum have hDen_sum : ∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ = ∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2 := by have hF_int : Integrable (fun ω => wD.Vtilde ω * wD.Vtilde ω) μ := wD.Vtilde_memLp.integrable_mul wD.Vtilde_memLp calc ∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ = ∑ g, ∑ t, ∫ ω, (wD.Vtilde ω * wD.Vtilde ω) * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω ∂μ := integral_eq_sum_panel_cell μ (fun ω => wD.Vtilde ω * wD.Vtilde ω) G T_rv G_meas T_meas hF_int _ = ∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2 := by refine Finset.sum_congr rfl (fun g _ => ?_) refine Finset.sum_congr rfl (fun t _ => ?_) simpa [wD, residWitnessD_panel, mul_assoc] using denom_per_cell_panel μ D G T_rv G_meas T_meas g t (hD_cell g t) calc ∫ ω, (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω * (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω ∂μ = ∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ := by rfl _ = ∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2 := hDen_sum _ = VD P := by simp [P, panelOf, VD, hLaw, hDtilde_eq]
theorem bridge_VD_pos_iff_Dtilde_sq_pos reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

On a probability space carrying cohort label G, period label T_rv, treatment D, and outcome Y, assume D is binary almost everywhere, there is at least one time period, every cohort has strictly positive population mass, the cohort masses sum to one, each cohort's mass is split evenly across periods (a balanced panel law), on each cohort-period cell D is almost-everywhere equal to its own cell mean (cell-measurability of D), and the population per-cell residualized treatment panelDtilde agrees with the finite-panel residualized treatment Dtilde. Then the finite-cell Goodman-Bacon denominator VD is strictly positive if and only if the population FWL denominator ∫ Vtilde² dμ is strictly positive.

Formal statement
Ω :
Type u_1
shared
𝒢 :
Type u_2
shared
T :
shared
D Y :
Ω → ℝ
G :
Ω → 𝒢
T_rv :
Ω → Fin T
A :
𝒢 → WithTop (Fin T)
G_meas :
T_meas :
D_meas :
D_binary :
∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1
B_balanced :
hT_pos :
0 < T
hp_pos :
∀ g, 0 < cohortMass μ G g
hp_sum :
∑ g, cohortMass μ G g = 1
hLaw :
∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)
hD_cell :
∀ g t,
∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω
= (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t
hDtilde_eq :
∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t
0 < VD (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum)
↔ 0 < ∫ ω, (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω * (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω ∂μ
Proof (Lean source)
theorem bridge_VD_pos_iff_Dtilde_sq_pos (μ : Measure Ω) [IsProbabilityMeasure μ] (D Y : Ω → ℝ) (G : Ω → 𝒢) (T_rv : Ω → Fin T) (A : 𝒢 → WithTop (Fin T)) (G_meas : Measurable G) (T_meas : Measurable T_rv) (D_meas : Measurable D) (D_binary : ∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1) (B_balanced : IsBalancedPanelLaw μ G T_rv) (hT_pos : 0 < T) (hp_pos : ∀ g, 0 < cohortMass μ G g) (hp_sum : ∑ g, cohortMass μ G g = 1) (hLaw : ∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)) (hD_cell : ∀ g t, ∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω = (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t) (hDtilde_eq : ∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t) : 0 < VD (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) ↔ 0 < ∫ ω, (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω * (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced).Vtilde ω ∂μ := by rw [bridge_Dtilde_sq_eq_VD μ D Y G T_rv A G_meas T_meas D_meas D_binary B_balanced hT_pos hp_pos hp_sum hLaw hD_cell hDtilde_eq]
theorem bridge_finite_residualized_eq_twfe reviewed
Causalean.Panel.EstimandCharacterization.StaggeredTWFEDecomposition

On a probability space carrying cohort label G, period label T_rv, treatment D, and outcome Y, assume D is binary almost everywhere, there is at least one time period, every cohort has strictly positive population mass, the cohort masses sum to one, each cohort's mass is split evenly across periods (a balanced panel law), on each cohort-period cell D is almost-everywhere equal to its own cell mean (cell-measurability of D), and the population per-cell residualized treatment panelDtilde agrees with the finite-panel residualized treatment Dtilde. Then the population residualized regression coefficient of D on Y, controlling for the cohort/period additive class panelClass, equals the finite-cell Goodman-Bacon two-way-fixed-effects coefficient betaTWFE of the induced finite panel.

Formal statement
Ω :
Type u_1
shared
𝒢 :
Type u_2
shared
T :
shared
D Y :
Ω → ℝ
G :
Ω → 𝒢
T_rv :
Ω → Fin T
A :
𝒢 → WithTop (Fin T)
G_meas :
T_meas :
D_meas :
D_binary :
∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1
Y_memLp :
MemLp Y 2 μ
B_balanced :
hT_pos :
0 < T
hp_pos :
∀ g, 0 < cohortMass μ G g
hp_sum :
∑ g, cohortMass μ G g = 1
hLaw :
∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)
hD_cell :
∀ g t,
∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω
= (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t
hDtilde_eq :
∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t
residualizedCoefficient μ (panelClass μ G T_rv G_meas T_meas) (residWitnessY_panel μ Y G T_rv G_meas T_meas Y_memLp B_balanced) (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced)
= betaTWFE (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum)
Proof (Lean source)
theorem bridge_finite_residualized_eq_twfe (μ : Measure Ω) [IsProbabilityMeasure μ] (D Y : Ω → ℝ) (G : Ω → 𝒢) (T_rv : Ω → Fin T) (A : 𝒢 → WithTop (Fin T)) (G_meas : Measurable G) (T_meas : Measurable T_rv) (D_meas : Measurable D) (D_binary : ∀ᵐ ω ∂μ, D ω = 0 ∨ D ω = 1) (Y_memLp : MemLp Y 2 μ) (B_balanced : IsBalancedPanelLaw μ G T_rv) (hT_pos : 0 < T) (hp_pos : ∀ g, 0 < cohortMass μ G g) (hp_sum : ∑ g, cohortMass μ G g = 1) (hLaw : ∀ g t, cellMass μ G T_rv g t = cohortMass μ G g / (T : ℝ)) (hD_cell : ∀ g t, ∀ᵐ ω ∂μ.restrict {ω' | G ω' = g ∧ T_rv ω' = t}, D ω = (∫ ω', D ω' * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω' ∂μ) / cellMass μ G T_rv g t) (hDtilde_eq : ∀ g t, panelDtilde μ D G T_rv g t = Dtilde (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) g t) : residualizedCoefficient μ (panelClass μ G T_rv G_meas T_meas) (residWitnessY_panel μ Y G T_rv G_meas T_meas Y_memLp B_balanced) (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced) = betaTWFE (panelOf μ Y G T_rv A hT_pos hp_pos hp_sum) := by let H := panelClass μ G T_rv G_meas T_meas let wY := residWitnessY_panel μ Y G T_rv G_meas T_meas Y_memLp B_balanced let wD := residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced let P := panelOf μ Y G T_rv A hT_pos hp_pos hp_sum have hMeanReg_mem : H.mem (panelMeanReg μ Y G T_rv) := panelMeanReg_mem_panelClass μ Y G T_rv G_meas T_meas have hNum_tilde : ∫ ω, wD.Vtilde ω * wY.Vtilde ω ∂μ = ∫ ω, wD.Vtilde ω * Y ω ∂μ := by have hDY_int : Integrable (fun ω => wD.Vtilde ω * Y ω) μ := wD.Vtilde_memLp.integrable_mul Y_memLp have hDM_int : Integrable (fun ω => wD.Vtilde ω * panelMeanReg μ Y G T_rv ω) μ := wD.Vtilde_memLp.integrable_mul (H.memLp hMeanReg_mem) calc ∫ ω, wD.Vtilde ω * wY.Vtilde ω ∂μ = ∫ ω, wD.Vtilde ω * Y ω - wD.Vtilde ω * panelMeanReg μ Y G T_rv ω ∂μ := by refine integral_congr_ae ?_ filter_upwards [] with ω simp [wY, residWitnessY_panel] ring _ = ∫ ω, wD.Vtilde ω * Y ω ∂μ - ∫ ω, wD.Vtilde ω * panelMeanReg μ Y G T_rv ω ∂μ := integral_sub hDY_int hDM_int _ = ∫ ω, wD.Vtilde ω * Y ω ∂μ := by rw [wD.orthogonal hMeanReg_mem] ring have hDen_sum : ∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ = ∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2 := by have hF_int : Integrable (fun ω => wD.Vtilde ω * wD.Vtilde ω) μ := wD.Vtilde_memLp.integrable_mul wD.Vtilde_memLp calc ∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ = ∑ g, ∑ t, ∫ ω, (wD.Vtilde ω * wD.Vtilde ω) * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω ∂μ := integral_eq_sum_panel_cell μ (fun ω => wD.Vtilde ω * wD.Vtilde ω) G T_rv G_meas T_meas hF_int _ = ∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2 := by refine Finset.sum_congr rfl (fun g _ => ?_) refine Finset.sum_congr rfl (fun t _ => ?_) simpa [wD, residWitnessD_panel, mul_assoc] using denom_per_cell_panel μ D G T_rv G_meas T_meas g t (hD_cell g t) have hNum_sum : ∫ ω, wD.Vtilde ω * Y ω ∂μ = ∑ g, ∑ t, cellMass μ G T_rv g t * panelDtilde μ D G T_rv g t * cellMean μ Y G T_rv g t := by have hF_int : Integrable (fun ω => wD.Vtilde ω * Y ω) μ := wD.Vtilde_memLp.integrable_mul Y_memLp calc ∫ ω, wD.Vtilde ω * Y ω ∂μ = ∑ g, ∑ t, ∫ ω, (wD.Vtilde ω * Y ω) * indicator {ω' | G ω' = g ∧ T_rv ω' = t} (fun _ => (1 : ℝ)) ω ∂μ := integral_eq_sum_panel_cell μ (fun ω => wD.Vtilde ω * Y ω) G T_rv G_meas T_meas hF_int _ = ∑ g, ∑ t, cellMass μ G T_rv g t * panelDtilde μ D G T_rv g t * cellMean μ Y G T_rv g t := by refine Finset.sum_congr rfl (fun g _ => ?_) refine Finset.sum_congr rfl (fun t _ => ?_) simpa [wD, residWitnessD_panel, mul_assoc] using num_per_cell_panel μ D Y G T_rv G_meas T_meas g t (hD_cell g t) calc residualizedCoefficient μ (panelClass μ G T_rv G_meas T_meas) (residWitnessY_panel μ Y G T_rv G_meas T_meas Y_memLp B_balanced) (residWitnessD_panel μ D G T_rv G_meas T_meas D_meas D_binary B_balanced) = (∫ ω, wD.Vtilde ω * wY.Vtilde ω ∂μ) / (∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ) := by rfl _ = (∫ ω, wD.Vtilde ω * Y ω ∂μ) / (∫ ω, wD.Vtilde ω * wD.Vtilde ω ∂μ) := by rw [hNum_tilde] _ = (∑ g, ∑ t, cellMass μ G T_rv g t * panelDtilde μ D G T_rv g t * cellMean μ Y G T_rv g t) / (∑ g, ∑ t, cellMass μ G T_rv g t * (panelDtilde μ D G T_rv g t)^2) := by rw [hNum_sum, hDen_sum] _ = betaTWFE P := by simp [P, panelOf, betaTWFE, VD, hLaw, hDtilde_eq, mul_assoc]