diff_diff.HADPretestReport#

class diff_diff.HADPretestReport[source]#

Bases: object

Composite output of did_had_pretest_workflow().

Two dispatch shapes, distinguished by aggregate:

aggregate="overall" (default, two-period panel): bundles paper steps 1 (QUG) and 3 (linearity via Stute + Yatchew-HR) on a two-period first-differenced sample. Step 2 (Assumption 7 pre-trends) is NOT implemented on this path and is explicitly flagged in the verdict; callers must run pre-trends separately.

aggregate="event_study" (multi-period panel, >= 3 periods): bundles QUG + joint pre-trends Stute + joint homogeneity-linearity Stute. The joint Stute variants close the paper step-2 gap; the event-study verdict does NOT emit the “paper step 2 deferred” caveat. Step 3 adjudication uses joint Stute only - no joint Yatchew variant exists because the paper does not derive one; users who need Yatchew robustness under multi-period data can run yatchew_hr_test() on each (base, post) pair manually.

qug#

Populated by default; None only when the workflow runs under survey= / weights= (Phase 4.5 C path), where the QUG step is permanently skipped per Phase 4.5 C0 (extreme-value theory under complex sampling not a settled toolkit; see qug_test()).

Type:

QUGTestResults or None

stute#

Populated when aggregate == "overall"; None when aggregate == "event_study".

Type:

StuteTestResults or None

yatchew#

Populated when aggregate == "overall"; None when aggregate == "event_study".

Type:

YatchewTestResults or None

pretrends_joint#

Populated when aggregate == "event_study" and at least one earlier pre-period exists; None on the overall path or when only the immediate base pre-period is available.

Type:

StuteJointResult or None

homogeneity_joint#

Populated when aggregate == "event_study"; None on the overall path.

Type:

StuteJointResult or None

all_pass#

On the unweighted overall path: same Phase 3 semantics - True iff QUG is conclusive AND at least one of Stute/Yatchew is conclusive AND no conclusive test rejects. On the unweighted event-study path: True iff np.isfinite(qug.p_value), pretrends_joint is not None and np.isfinite(pretrends_joint.p_value), np.isfinite(homogeneity_joint.p_value), AND none of the three rejects. On the survey/weights path (Phase 4.5 C) the QUG-conclusiveness gate is dropped (qug=None per C0 deferral); the linearity-conditional rule splits by aggregate:

  • aggregate="overall" survey: True iff at least one of Stute/Yatchew is conclusive AND no conclusive test rejects.

  • aggregate="event_study" survey: True iff pretrends_joint is non-None and conclusive, homogeneity_joint is conclusive, AND neither rejects. (Both joint variants must be conclusive on the event-study path - same step-2 + step-3 closure as the unweighted aggregate, just without the QUG step.)

Mirrors Phase 3’s bool(np.isfinite(p_value)) convention - no .conclusive() helper on any result dataclass.

Type:

bool

verdict#

Human-readable classification. Paper rule applies symmetrically: TWFE is admissible only if NONE of the implemented tests rejects. Conclusive rejections are the primary verdict; unresolved steps append as "; additional steps unresolved: ..." rather than replacing the rejection.

Type:

str

alpha#
Type:

float

n_obs#

Unit count. For overall: units after two-period first-difference aggregation. For event_study: units after balanced-panel validation and (if applicable) last-cohort auto-filter.

Type:

int

aggregate#

"overall" or "event_study". Determines which component fields are populated and which branch of serialization methods to render.

Type:

str

Methods

__init__(qug, stute, yatchew, all_pass, ...)

print_summary()

Print the summary to stdout.

summary()

Formatted summary of all tests and the verdict.

to_dataframe()

Return a tidy 3-row DataFrame (one row per implemented test).

to_dict()

Return a JSON-safe nested dict of the full report.

Attributes

__init__(qug, stute, yatchew, all_pass, verdict, alpha, n_obs, pretrends_joint=None, homogeneity_joint=None, aggregate='overall')#
Parameters:
Return type:

None

classmethod __new__(*args, **kwargs)#