Learn R Programming

fixes

Overview

Note
By default, the fixes package assumes time is a regularly spaced numeric variable (e.g., year = 1995, 1996, …).
If your time variable is irregular or non-numeric (e.g., Date type), set time_transform = TRUE to automatically convert it to a sequential index within each unit.
For unit-specific treatment timing, set staggered = TRUE.

The fixes package is designed for convenient event study analysis and plotting, particularly useful for visualizing parallel trends and dynamic effects in two-way fixed effects (TWFE) difference-in-differences (DID) research.

Key Functions:

  1. run_es() — Takes a data frame, generates lead/lag dummies, and fits the event study regression. Supports fixed effects, covariates, clustering, staggered timing, weights, custom baseline, and multiple confidence intervals.
  2. plot_es() — Plots event study results using ggplot2 with flexible options: ribbon or error bars, choice of CI level, and theme customization.

Installation

Install from CRAN:

install.packages("fixes")

Or with pak:

pak::pak("fixes")

For the latest development version from GitHub:

pak::pak("yo5uke/fixes")

How to use

First, load the library.

library(fixes)

Data frame requirements

run_es() expects a panel data frame with at least:

  • Unit identifier (e.g., individual, firm, region)
  • Treatment indicator (0/1 or TRUE/FALSE)
  • Time variable (numeric or Date)
  • Outcome variable (continuous)

For staggered adoption (staggered = TRUE), include a variable specifying unit-specific treatment timing (e.g., “treatment_year”).

Example data

Widely used panel datasets include:

  • did::sim_dt(): simulated panel for DiD tutorials
  • fixest::base_stagg: a built-in dataset for staggered adoption
df1 <- fixest::base_did      # Basic DiD
df2 <- fixest::base_stagg    # Staggered treatment
yx1idperiodposttreat
2.87530630.53653771101
1.8606527-3.04318941201
0.09416525.57684391301
3.7814749-2.83005871401
-2.5581996-5.04435441501
1.7287324-0.63638491611
idyearyear_treatedtime_to_treatmenttreatedtreatment_effect_truex1y
29012-110-1.09470210.0172297
38913-210-3.7100676-4.5808453
48814-3102.52744022.7381717
58715-410-0.7204263-0.6510307
68616-510-3.6711678-5.3338166
78517-610-0.31521370.4956263

run_es()

The main event study function. All key arguments below:

ArgumentDescription
dataData frame to be used.
outcomeOutcome variable. Can be specified as a raw variable or a transformation (e.g., log(y)). Provide it unquoted.
treatmentDummy variable indicating the treated units. Provide it unquoted. Accepts both 0/1 and TRUE/FALSE.
timeTime variable. Provide it unquoted.
timingThe time at which the treatment occurs. If staggered = FALSE, this should be a scalar (e.g., 2005). If staggered = TRUE, provide a variable (column) indicating the treatment time for each unit.
feFixed effects to control for unobserved heterogeneity. Must be a one-sided formula (e.g., ~ id + year).
lead_rangeNumber of pre-treatment periods to include (e.g., 3 = lead3, lead2, lead1). Default is NULL, which automatically uses the maximum available lead range.
lag_rangeNumber of post-treatment periods to include (e.g., 2 = lag0 (the treatment period), lag1, lag2). Default is NULL, which automatically uses the maximum available lag range.
covariatesAdditional covariates to include in the regression. Must be a one-sided formula (e.g., ~ x1 + x2).
clusterSpecifies clustering for standard errors. Can be a character vector (e.g., c("id", "year")) or a formula (e.g., ~ id + year, ~ id^year).
weightsOptional weights to be used in the regression. Provide as a one-sided formula (e.g., ~ weight).
baselineRelative time value to be used as the reference category. The corresponding dummy is excluded from the regression. Must be within the specified lead/lag range.
intervalTime interval between observations (e.g., 1 for yearly data, 5 for 5-year intervals).
time_transformLogical. If TRUE, converts the time variable into a sequential index (1, 2, 3, …) within each unit. Useful for irregular time (e.g., Date). Default is FALSE.
unitRequired if time_transform = TRUE. Specifies the panel unit identifier (e.g., firm_id).
staggeredLogical. If TRUE, allows for unit-specific treatment timing (staggered adoption). Default is FALSE.
conf.levelNumeric vector of confidence levels (e.g., c(0.90, 0.95, 0.99); default: 0.95).

Example: basic event study

event_study <- run_es(
  data       = df1,
  outcome    = y,
  treatment  = treat,
  time       = period,
  timing     = 6,
  fe         = ~ id + period,
  lead_range = 5,
  lag_range  = 4,
  cluster    = ~ id,
  baseline   = -1,
  interval   = 1,
  conf.level = c(0.90, 0.95, 0.99)
)
  • fe must be a one-sided formula (e.g., ~ firm_id + year).
  • cluster can be a one-sided formula or a character vector.

With covariates

event_study <- run_es(
  data       = df1,
  outcome    = y,
  treatment  = treat,
  time       = period,
  timing     = 6,
  fe         = ~ id + period,
  lead_range = 5,
  lag_range  = 4,
  covariates = ~ cov1 + cov2 + cov3,
  cluster    = ~ id,
  baseline   = -1,
  interval   = 1
)

Using irregular time data (Date), with time_transform

df_alt <- df1 |>
  dplyr::mutate(
    year = rep(2001:2010, times = 108),
    date = as.Date(paste0(year, "-01-01"))
  )

event_study_alt <- run_es(
  data           = df_alt,
  outcome        = y,
  treatment      = treat,
  time           = date,
  timing         = 9,  # Use index, not the original Date
  fe             = ~ id + period,
  lead_range     = 3,
  lag_range      = 3,
  cluster        = ~ id,
  baseline       = -1,
  time_transform = TRUE,
  unit           = id
)

Note:
When time_transform = TRUE, specify timing as an index (e.g., 9 = 9th observation in unit).
Currently, time_transform = TRUE cannot be combined with staggered = TRUE (future versions may support this).

plot_es()

plot_es() visualizes results using ggplot2. By default, it plots a ribbon for the 95% CI, but supports error bars, CI level selection, and multiple themes.

ArgumentDescription
dataData frame from run_es()
ci_levelConfidence interval (default: 0.95)
type“ribbon” (default) or “errorbar”
vline_valX for vertical line (default: 0)
vline_colorColor for vline (default: “#000”)
hline_valY for horizontal line (default: 0)
hline_colorColor for hline (default: “#000”)
linewidthLine width (default: 1)
pointsizePoint size (default: 2)
alphaRibbon transparency (default: 0.2)
barwidthErrorbar width (default: 0.2)
colorPoint/line color (default: “#B25D91FF”)
fillRibbon color (default: “#B25D91FF”)
theme_styleTheme: “bw” (default), “minimal”, “classic”

Example usage

plot_es(event_study)
plot_es(event_study, type = "errorbar")
plot_es(event_study, type = "ribbon", ci_level = 0.9, theme_style = "minimal")
plot_es(event_study, type = "errorbar", ci_level = 0.99) + ggplot2::ggtitle("Event Study, 99% CI")

Further customization with ggplot2 is fully supported:

plot_es(event_study, type = "errorbar") + 
  ggplot2::scale_x_continuous(breaks = seq(-5, 5, by = 1)) + 
  ggplot2::ggtitle("Result of Event Study")

Planned Features

  • Support for staggered = TRUE with time_transform = TRUE
  • Allow timing to accept original time values (e.g., Date), not just index

Debugging and Contributions

If you find an issue or want to contribute, please use the GitHub Issues page.


Happy analyzing!

Copy Link

Version

Install

install.packages('fixes')

Monthly Downloads

434

Version

0.5.0

License

MIT + file LICENSE

Issues

Pull Requests

Stars

Forks

Maintainer

Yosuke Abe

Last Published

July 7th, 2025

Functions in fixes (0.5.0)

run_es

Event Study Estimation for Panel Data
plot_es

Plot Event Study Results