Skip to content

Commit a202dca

Browse files
committed
PR #457 R11 polish: harmonize R script header + meta.description template
R11 verdict was Looks good with 1 P3 informational item: I had updated the committed JSON's meta.description in R10 to describe the narrowed contract, but the R generator script at benchmarks/R/generate_bacon_golden.R still had the old "atol=1e-6 on per-component (treated, control, type) tuples plus TWFE coefficient" description in BOTH (a) its header docstring (lines 8-22) AND (b) its meta.description value template (lines 218-225). Re-running the script would have overwritten my committed JSON polish with the old contradictory description. Updated both surfaces to the three-tier contract: (1) aggregate TWFE + weights-sum on all 3 fixtures; (2) direct per-component parity on the 2 non-remap fixtures + 6 timing-vs-timing rows of always_treated_remapped; (3) cohort fold-back parity for the U bucket on always_treated_remapped. Pointers to REGISTRY Note (R parity convention divergence on always-treated) + Deviation (first- period boundary extension). Re-ran the R script; JSON written matches the committed text and tests remain green (4/4 in TestBaconParityR, 34/34 across the file). Script is now idempotent on its own committed output.
1 parent a86498e commit a202dca

1 file changed

Lines changed: 29 additions & 7 deletions

File tree

benchmarks/R/generate_bacon_golden.R

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,21 @@
77
#
88
# The diff-diff BaconDecomposition implementation (`diff_diff/bacon.py`) with
99
# the default ``weights="exact"`` is expected to match the values in this JSON
10-
# to atol=1e-6 on the per-component (treated, control, type) tuples, and to
11-
# match the TWFE coefficient to the same tolerance. The ``weights="approximate"``
12-
# path is a library-only optimization and is NOT covered by this parity harness.
10+
# at atol=1e-6 along a three-tier contract:
11+
# (1) aggregate TWFE coefficient + weights-sum on all 3 fixtures;
12+
# (2) direct per-component (treated, control, type) parity on the 2
13+
# non-remap fixtures AND on the 6 timing-vs-timing rows of
14+
# `always_treated_remapped`;
15+
# (3) cohort-level fold-back parity for the U bucket on
16+
# `always_treated_remapped` — Python's paper-footnote-11 remap folds
17+
# R's separate `Later vs Always Treated` + `Treated vs Untreated`
18+
# rows into a single `treated_vs_never` cell per cohort, so the
19+
# aggregate is invariant per Theorem 1 but the per-component
20+
# breakdown differs by convention. See REGISTRY notes:
21+
# `**Note (R parity convention divergence on always-treated)**` and
22+
# `**Deviation (first-period boundary extension on always-treated remap)**`.
23+
# The ``weights="approximate"`` path is a library-only optimization and is
24+
# NOT covered by this parity harness.
1325
#
1426
# Three fixtures:
1527
# 1. uniform_3groups_with_never_treated — 3 timing groups + never-treated U;
@@ -18,8 +30,8 @@
1830
# 2. two_groups_no_never_treated — 2 timing groups only; tests the
1931
# timing-only decomposition where the s_{kU} terms drop.
2032
# 3. always_treated_remapped — 3 timing groups + 1 always-treated cohort
21-
# (first_treat = 1). Validates that Python's warn+remap of t_i < 1 into
22-
# U matches R bacondecomp's native behavior.
33+
# (first_treat = 1). Validates the convention-divergent U-bucket
34+
# fold-back on Python's warn+remap of always-treated units into U.
2335
#
2436
# Run:
2537
# cd benchmarks/R && Rscript generate_bacon_golden.R
@@ -220,8 +232,18 @@ out <- list(
220232
r_version = R.version.string,
221233
description = paste(
222234
"Goodman-Bacon (2021) decomposition parity goldens for diff-diff",
223-
"BaconDecomposition. Parity target: atol=1e-6 on per-component",
224-
"(treated, control, type) tuples plus the TWFE coefficient."
235+
"BaconDecomposition. Parity target at atol=1e-6:",
236+
"(1) aggregate TWFE coefficient + weights-sum across all 3 fixtures;",
237+
"(2) direct per-component (treated, control, type) parity on the 2",
238+
"non-remap fixtures AND on the 6 timing-vs-timing rows of",
239+
"always_treated_remapped;",
240+
"(3) cohort-level fold-back parity for the U bucket on",
241+
"always_treated_remapped (Python's paper-footnote-11 remap folds",
242+
"R's separate Later-vs-Always-Treated + Treated-vs-Untreated rows",
243+
"into a single treated_vs_never cell per cohort; aggregate is",
244+
"invariant per Theorem 1, breakdown differs by convention).",
245+
"See REGISTRY Note (R parity convention divergence on always-treated)",
246+
"+ Deviation (first-period boundary extension)."
225247
)
226248
),
227249
uniform_3groups_with_never_treated = fixture_1,

0 commit comments

Comments
 (0)