--- title: "didintrjl" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{didintrjl} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` ```{r setup} library(didintrjl) ``` ```{r, include = FALSE} # Only run the examples below if Julia can be set up on this machine. # (DiDInt.jl must also be installed; see the README.) knitr::opts_chunk$set( eval = requireNamespace("JuliaConnectoR", quietly = TRUE) && JuliaConnectoR::juliaSetupOk() && JuliaConnectoR::juliaEval('using Pkg; _didint_pkgs = filter(p -> p.second.name == "DiDInt", Pkg.dependencies()); !isempty(_didint_pkgs) && first(values(_didint_pkgs)).version >= v"0.9.6"') #nolint ) ``` ## Introduction The **didintrjl** package is an R wrapper for the Julia package [DiDInt.jl](https://ebjamieson97.github.io/DiDInt.jl/stable/), which implements intersection difference-in-differences (DID-INT); a method developed by [Karim & Webb (2025)](https://arxiv.org/abs/2412.14447). DID-INT allows for unbiased estimation of the average treatment effect on the treated (ATT) when the common causal covariates (CCC) assumption is violated; that is, when the effects of covariates on the outcome of interest may vary by state, time, or both. It supports common or staggered adoption. Because **didintrjl** interfaces with Julia via [JuliaConnectoR](https://github.com/stefan-m-lenz/JuliaConnectoR), the examples below require a working Julia installation with **DiDInt.jl** available (see the README for installation details). They are evaluated only when `juliaSetupOk()` returns `TRUE` and the **DiDInt.jl** package can be found. The two functions are `didint()`, which estimates ATT, and `didint_plot()`, which produces parallel trends or event study plots. ## 1. Estimation `didint()` returns an object of class `DiDIntObj` with three S3 methods: `print()`, `summary()`, and `coef()`. Each accepts a `level` argument of either `"agg"` or `"sub"` to distinguish aggregate from sub-aggregate results. In a staggered adoption setting with several treatment times, `level = "sub"` returns results for the distinct treatment times, whereas `level = "agg"` returns the aggregated results. ```{r} # Load the example data df <- read.csv(system.file("extdata", "merit.csv", package = "didintrjl")) # Estimate the ATT res <- didint("coll", "state", "year", df, verbose = FALSE, treated_states = c(71, 58, 64, 59, 85, 57, 72, 61, 34, 88), treatment_times = c(1991, 1993, 1996, 1997, 1997, 1998, 1998, 1999, 2000, 2000)) summary(res) # Aggregate and sub-aggregate results can also be accessed directly res$agg res$sub ``` ## 2. Plotting `didint_plot()` returns an object of class `DiDIntPlotObj` with one S3 method: `plot()`. It can produce either an event study plot (`event = TRUE`) or a parallel trends plot (the default). The object also stores the underlying plotting data in `DiDIntPlotObj$data`, so you can build your own customized plots if you wish. ### 2.1 Event Study Plot ```{r, fig.width = 9, fig.height = 10, out.width = "100%", fig.align = "center"} res_event <- didint_plot("coll", "state", "year", df, event = TRUE, treated_states = c(71, 58, 64, 59, 85, 57, 72, 61, 34, 88), treatment_times = c(1991, 1993, 1996, 1997, 1997, 1998, 1998, 1999, 2000, 2000), covariates = c("asian", "black", "male")) plot(res_event) ``` ### 2.2 Parallel Trends Plot ```{r, fig.width = 8, fig.height = 6, out.width = "100%", fig.align = "center"} # Using a subset of states to keep the plot readable df_sub <- df[df$state %in% c(71, 58, 11, 34, 14), ] res_parallel <- didint_plot("coll", "state", "year", df_sub, treatment_times = c(1991, 1993, 2000), covariates = c("asian", "black", "male")) plot(res_parallel) ``` For both plot types you can choose which combination of plots to view via the `ccc` argument, e.g. `plot(res_parallel, ccc = "state")` or `plot(res_event, ccc = c("none", "hom", "int"))`. The plotting data itself is available via `res_parallel$data` and `res_event$data`. ```{r, include = FALSE} # Shut down the Julia session started during the examples. if (requireNamespace("JuliaConnectoR", quietly = TRUE) && JuliaConnectoR::juliaSetupOk()) { JuliaConnectoR:::stopJulia() } ``` ## References You can access citations by calling `citation("didintrjl")`. Karim, S. and Webb, M. D. 2025. Good Controls Gone Bad: Difference-in-Differences with Covariates. arXiv preprint arXiv:2412.14447. [https://arxiv.org/abs/2412.14447](https://arxiv.org/abs/2412.14447)