Visualization

Plotting functions for DiD results visualization.

plot_event_study

Create publication-ready event study coefficient plots.

diff_diff.plot_event_study(results=None, *, effects=None, se=None, periods=None, reference_period=None, pre_periods=None, post_periods=None, alpha=0.05, figsize=(10, 6), title='Event Study', xlabel='Period Relative to Treatment', ylabel='Treatment Effect', color='#2563eb', marker='o', markersize=8, linewidth=1.5, capsize=4, show_zero_line=True, show_reference_line=True, shade_pre=True, shade_color='#f0f0f0', ax=None, show=True)[source]

Create an event study plot showing treatment effects over time.

This function creates a coefficient plot with point estimates and confidence intervals for each time period, commonly used to visualize dynamic treatment effects and assess pre-trends.

Parameters:
  • results (MultiPeriodDiDResults, CallawaySantAnnaResults, or DataFrame, optional) – Results object from MultiPeriodDiD, CallawaySantAnna, or a DataFrame with columns ‘period’, ‘effect’, ‘se’ (and optionally ‘conf_int_lower’, ‘conf_int_upper’). If None, must provide effects and se directly.

  • effects (dict, optional) – Dictionary mapping periods to effect estimates. Used if results is None.

  • se (dict, optional) – Dictionary mapping periods to standard errors. Used if results is None.

  • periods (list, optional) – List of periods to plot. If None, uses all periods from results.

  • reference_period (any, optional) – The reference period to highlight. When explicitly provided, effects are normalized (ref effect subtracted) and ref SE is set to NaN. When None and auto-inferred from results, only hollow marker styling is applied (no normalization). If None, tries to infer from results.

  • pre_periods (list, optional) – List of pre-treatment periods. Used for shading.

  • post_periods (list, optional) – List of post-treatment periods. Used for shading.

  • alpha (float, default=0.05) – Significance level for confidence intervals.

  • figsize (tuple, default=(10, 6)) – Figure size (width, height) in inches.

  • title (str, default="Event Study") – Plot title.

  • xlabel (str, default="Period Relative to Treatment") – X-axis label.

  • ylabel (str, default="Treatment Effect") – Y-axis label.

  • color (str, default="#2563eb") – Color for points and error bars.

  • marker (str, default="o") – Marker style for point estimates.

  • markersize (int, default=8) – Size of markers.

  • linewidth (float, default=1.5) – Width of error bar lines.

  • capsize (int, default=4) – Size of error bar caps.

  • show_zero_line (bool, default=True) – Whether to show a horizontal line at y=0.

  • show_reference_line (bool, default=True) – Whether to show a vertical line at the reference period.

  • shade_pre (bool, default=True) – Whether to shade the pre-treatment region.

  • shade_color (str, default="#f0f0f0") – Color for pre-treatment shading.

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, creates new figure.

  • show (bool, default=True) – Whether to call plt.show() at the end.

Returns:

The axes object containing the plot.

Return type:

matplotlib.axes.Axes

Examples

Using with MultiPeriodDiD results:

>>> from diff_diff import MultiPeriodDiD, plot_event_study
>>> did = MultiPeriodDiD()
>>> results = did.fit(data, outcome='y', treatment='treated',
...                   time='period', post_periods=[3, 4, 5])
>>> plot_event_study(results)

Using with a DataFrame:

>>> df = pd.DataFrame({
...     'period': [-2, -1, 0, 1, 2],
...     'effect': [0.1, 0.05, 0.0, 0.5, 0.6],
...     'se': [0.1, 0.1, 0.0, 0.15, 0.15]
... })
>>> plot_event_study(df, reference_period=0)

Using with manual effects:

>>> effects = {-2: 0.1, -1: 0.05, 0: 0.0, 1: 0.5, 2: 0.6}
>>> se = {-2: 0.1, -1: 0.1, 0: 0.0, 1: 0.15, 2: 0.15}
>>> plot_event_study(effects=effects, se=se, reference_period=0)

Notes

Event study plots are a standard visualization in difference-in-differences analysis. They show:

  1. Pre-treatment periods: Effects should be close to zero if parallel trends holds. Large pre-treatment effects suggest the assumption may be violated.

  2. Reference period: Usually the last pre-treatment period (t=-1). When explicitly specified via reference_period, effects are normalized to zero at this period. When auto-inferred, shown with hollow marker only.

  3. Post-treatment periods: The treatment effects of interest. These show how the outcome evolved after treatment.

The confidence intervals help assess statistical significance. Effects whose CIs don’t include zero are typically considered significant.

Example

from diff_diff import MultiPeriodDiD, plot_event_study

# Fit event study model
model = MultiPeriodDiD(reference_period=-1)
results = model.fit(data, outcome='y', treated='treated',
                    time='period', unit='unit_id', treatment_start=5)

# Create plot
fig = plot_event_study(results)
fig.savefig('event_study.png', dpi=300, bbox_inches='tight')

plot_group_effects

Visualize treatment effects by cohort.

diff_diff.plot_group_effects(results, *, groups=None, figsize=(10, 6), title='Treatment Effects by Cohort', xlabel='Time Period', ylabel='Treatment Effect', alpha=0.05, show=True, ax=None)[source]

Plot treatment effects by treatment cohort (group).

Parameters:
  • results (CallawaySantAnnaResults) – Results from CallawaySantAnna estimator.

  • groups (list, optional) – List of groups (cohorts) to plot. If None, plots all groups.

  • figsize (tuple, default=(10, 6)) – Figure size.

  • title (str) – Plot title.

  • xlabel (str) – X-axis label.

  • ylabel (str) – Y-axis label.

  • alpha (float, default=0.05) – Significance level for confidence intervals.

  • show (bool, default=True) – Whether to call plt.show().

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on.

Returns:

The axes object.

Return type:

matplotlib.axes.Axes

Example

from diff_diff import CallawaySantAnna, plot_group_effects

cs = CallawaySantAnna()
results = cs.fit(data, outcome='y', unit='unit_id',
                 time='period', first_treat='first_treat')

# Plot effects by treatment cohort
fig = plot_group_effects(results)

plot_sensitivity

Plot Honest DiD sensitivity analysis results.

diff_diff.plot_sensitivity(sensitivity_results, *, show_bounds=True, show_ci=True, breakdown_line=True, figsize=(10, 6), title='Honest DiD Sensitivity Analysis', xlabel='M (restriction parameter)', ylabel='Treatment Effect', bounds_color='#2563eb', bounds_alpha=0.3, ci_color='#2563eb', ci_linewidth=1.5, breakdown_color='#dc2626', original_color='#1f2937', ax=None, show=True)[source]

Plot sensitivity analysis results from Honest DiD.

Shows how treatment effect bounds and confidence intervals change as the restriction parameter M varies.

Parameters:
  • sensitivity_results (SensitivityResults) – Results from HonestDiD.sensitivity_analysis().

  • show_bounds (bool, default=True) – Whether to show the identified set bounds as shaded region.

  • show_ci (bool, default=True) – Whether to show robust confidence interval lines.

  • breakdown_line (bool, default=True) – Whether to show vertical line at breakdown value.

  • figsize (tuple, default=(10, 6)) – Figure size (width, height) in inches.

  • title (str) – Plot title.

  • xlabel (str) – X-axis label.

  • ylabel (str) – Y-axis label.

  • bounds_color (str) – Color for identified set shading.

  • bounds_alpha (float) – Transparency for identified set shading.

  • ci_color (str) – Color for confidence interval lines.

  • ci_linewidth (float) – Line width for CI lines.

  • breakdown_color (str) – Color for breakdown value line.

  • original_color (str) – Color for original estimate line.

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, creates new figure.

  • show (bool, default=True) – Whether to call plt.show().

Returns:

The axes object containing the plot.

Return type:

matplotlib.axes.Axes

Examples

>>> from diff_diff import MultiPeriodDiD
>>> from diff_diff.honest_did import HonestDiD
>>> from diff_diff.visualization import plot_sensitivity
>>>
>>> # Fit event study and run sensitivity analysis
>>> results = MultiPeriodDiD().fit(data, ...)
>>> honest = HonestDiD(method='relative_magnitude')
>>> sensitivity = honest.sensitivity_analysis(results)
>>>
>>> # Create sensitivity plot
>>> plot_sensitivity(sensitivity)

Example

from diff_diff import HonestDiD, DeltaRM, plot_sensitivity

honest = HonestDiD(delta=DeltaRM(M_bar=1.0))
sensitivity = honest.sensitivity_analysis(
    results,
    M_grid=[0, 0.5, 1.0, 1.5, 2.0]
)

fig = plot_sensitivity(sensitivity)

plot_honest_event_study

Event study plot with honest confidence intervals.

diff_diff.plot_honest_event_study(honest_results, *, periods=None, reference_period=None, figsize=(10, 6), title='Event Study with Honest Confidence Intervals', xlabel='Period Relative to Treatment', ylabel='Treatment Effect', original_color='#6b7280', honest_color='#2563eb', marker='o', markersize=8, capsize=4, ax=None, show=True)[source]

Create event study plot with Honest DiD confidence intervals.

Shows both the original confidence intervals (assuming parallel trends) and the robust confidence intervals that allow for bounded violations.

Parameters:
  • honest_results (HonestDiDResults) – Results from HonestDiD.fit() that include event_study_bounds.

  • periods (list, optional) – Periods to plot. If None, uses all available periods.

  • reference_period (any, optional) – Reference period to show as hollow marker.

  • figsize (tuple, default=(10, 6)) – Figure size.

  • title (str) – Plot title.

  • xlabel (str) – X-axis label.

  • ylabel (str) – Y-axis label.

  • original_color (str) – Color for original (standard) confidence intervals.

  • honest_color (str) – Color for honest (robust) confidence intervals.

  • marker (str) – Marker style.

  • markersize (int) – Marker size.

  • capsize (int) – Error bar cap size.

  • ax (matplotlib.axes.Axes, optional) – Axes to plot on.

  • show (bool, default=True) – Whether to call plt.show().

Returns:

The axes object.

Return type:

matplotlib.axes.Axes

Notes

This function requires the HonestDiDResults to have been computed with event_study_bounds. If only a scalar bound was computed, use plot_sensitivity() instead.

Example

from diff_diff import HonestDiD, DeltaRM, plot_honest_event_study

honest = HonestDiD(delta=DeltaRM(M_bar=1.0))
bounds = honest.fit(event_study_results)

fig = plot_honest_event_study(event_study_results, bounds)