contdid
Difference-in-Differences with a Continuous Treatment
Science Score: 54.0%
This score indicates how likely this project is to be science-related based on various indicators:
-
✓CITATION.cff file
Found CITATION.cff file -
✓codemeta.json file
Found codemeta.json file -
✓.zenodo.json file
Found .zenodo.json file -
○DOI references
-
✓Academic publication links
Links to: arxiv.org -
○Academic email domains
-
○Institutional organization owner
-
○JOSS paper metadata
-
○Scientific vocabulary similarity
Low similarity (18.1%) to scientific vocabulary
Last synced: 6 months ago
·
JSON representation
·
Repository
Difference-in-Differences with a Continuous Treatment
Basic Info
- Host: GitHub
- Owner: bcallaway11
- Language: R
- Default Branch: main
- Homepage: https://bcallaway11.github.io/contdid/
- Size: 2.2 MB
Statistics
- Stars: 32
- Watchers: 1
- Forks: 3
- Open Issues: 3
- Releases: 0
Created over 1 year ago
· Last pushed 8 months ago
Metadata Files
Readme
Changelog
Citation
README.Rmd
---
output: github_document
references:
- id: callaway-goodman-santanna-2025
title: "Difference-in-Differences with a Continuous Treatment"
author:
- family: Callaway
given: Brantly
- family: Goodman-Bacon
given: Andrew
- family: Sant'Anna
given: Pedro H. C.
issued:
year: 2025
type: unpublished
note: "Working paper"
- id: chen-christensen-kankanala-2025
title: "Adaptive Estimation and Uniform Confidence Bands for Nonparametric Structural Functions and Elasticities"
author:
- family: Chen
given: Xiaohong
- family: Christensen
given: Timothy
- family: Kankanala
given: Sid
issued:
year: 2025
container-title: "Review of Economic Studies"
volume: 92
issue: 1
page: 162–196
type: article-journal
---
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# contdid
An R package for difference-in-differences with a continuous treatment.
## Installation
You can install the development version of contdid from [GitHub](https://github.com/bcallaway11/contdid) with:
```{r, eval=FALSE}
# install.packages("devtools")
devtools::install_github("bcallaway11/contdid")
library(contdid)
```
## Package Status: Alpha Version
This is an **alpha version** of the `contdid` package. The core features are implemented and functional, but the package remains under active development. The API may change, and additional functionality is planned.
We welcome feedback and encourage users to report bugs or other issues via the [GitHub Issues page](https://github.com/bcallaway11/contdid/issues).
### ✅ Currently Supported
- ☑️ Continuous treatments
- ☑️ Staggered treatment adoption (i.e., more than two periods and variation in timing across units)
- ☑️ Aggregations into dose-specific ATT's or ACRT's
- ☑️ Aggregations into ATT or ACRT versions of event studies
- ☑️ User-specified flexible parametric models for treatment effects as a function of the dose
### 🚫 Not Yet Supported
- ❌ Discrete treatments
- This is straightforward and could be implemented by users directly, but we don't have it in the package yet.
- ⚠️ Data-driven models for treatment effects as a function of the dose
- We have this working for cases without staggered adoption, but it is not yet implemented for staggered adoption. We plan to add this in the future.
- ❌ Repeated cross-sections data
- ❌ Unbalanced panel data
- ❌ Doses that vary over time
- Not sure if we will ever support this, or maybe only in limited contexts._
- ❌ Including covariates
```{r, echo=FALSE, warning=FALSE, message=FALSE}
devtools::load_all("~/Dropbox/BMisc")
devtools::load_all("~/Dropbox/ptetools")
devtools::load_all("~/Dropbox/contdid")
```
## Conceptual Setup
Below, we give several examples of how to estimate causal effect parameters using the `contdid` package.
At a high level, the interface is basically the same as for the `did` package and for packages that rely on the `ptetools` backend, with only a few pieces of additional information being required. First, the name of the continuous treatment variable should be passed through the `dname` argument.
The `cont_did` function expects the continuous treatment variable to behave in certain ways:
1. It needs to be time-invariant.
2. It should be set to its time-invariant value in pre-treatment periods. This is just a convention of the package, but, in particular, you should not have the treatment variable coded as being 0 in pre-treatment periods.
3. For units that don't participate in the treatment in any time period, the treatment variable just needs to be time-invariant. In some applications, e.g., the continuous treatment variable may be defined for units that don't actually participate in the treatment. In other applications, it may not be defined for units that do not participate in the treatment. The function behaves the same way in either case.
Next, the other important parameters are `target_parameter`, `aggregation`, and `treatment_type`:
* `target_parameter` can either be "level" or "slope". If "level", then the function will calculate `ATT` parameters. If set to be "slope", then the function will calculate `ACRT` parameters---these are causal response parameters that are derivatives of the `ATT` parameters. Our paper [Callaway, Goodman-Bacon, and Sant'Anna (2024)](https://arxiv.org/abs/2107.02637) points out some complications for interpreting these derivative type parameters under the most commonly invoked version of the parallel trends assumption.
* `aggregation` can either by "eventstudy" or "dose". For "eventstudy", depending on the value of the `target_parameter` argument, the function will provide either the average `ATT` across different event times or the average `ACRT` across different event times. For "dose", the function will average across all time periods and report average affects across different values of the continuous treatment. For the "dose" aggregation, results are calculated for both `ATT` and `ACRT` and can be displayed by providing different arguments to plotting functions (see example below).
* `treatment_type` can either be "continuous" or "discrete". Currently only "continuous" is supported. In this case, the code proceeds as if the treatment really is continuous. The estimate are computed nonparametrically using B-splines. The user can control the number of knots and the degree of the B-splines using the `num_knots` and `degree` arguments. The defaults are `num_knots=0` and `degree=1` which amounts to estimating `ATT(d)` by estimating a linear model in the continuous treatment among treated units and subtracting the average outcome among the comparison units.
## Examples
With a continuous treatment, the underlying building blocks are treatment effects that are local to a particular timing group `g` in a particular time period `t` that experienced a particular value of the treatment `d`. These treatment affects are relatively high-dimensional, and most applications are likely to involve aggregating/combining these underlying parameters. We focus on aggregations that (i) average across timing-groups and time periods to given average treatment effect parameters as a function of the dose `d` or (ii) averages across doses and partially across timing group and time periods in order to give event studies.
For the results below, we will simulate some data, where the continuous treatment `D` has no effect on the outcome.
```{r}
# Simulate data
set.seed(1234)
df <- simulate_contdid_data(
n = 5000,
num_time_periods = 4,
num_groups = 4,
dose_linear_effect = 0,
dose_quadratic_effect = 0
)
head(df)
```
### Case 1: Dose Aggregation
The following code can be used to estimate the `ATT(d)` and `ACRT(d)` parameters for the continuous treatment `D` using the `cont_did` function. The `aggregation` argument is set to "dose" and the `target_parameter` argument is set to "level" for `ATT(d)` and "slope" for `ACRT(d)`.
```{r, warning=FALSE, message=FALSE}
cd_res <- cont_did(
yname = "Y",
tname = "time_period",
idname = "id",
dname = "D",
data = df,
gname = "G",
target_parameter = "slope",
aggregation = "dose",
treatment_type = "continuous",
control_group = "notyettreated",
biters = 100,
cband = TRUE,
num_knots = 1,
degree = 3,
)
summary(cd_res)
ggcont_did(cd_res, type = "att")
ggcont_did(cd_res, type = "acrt")
```
### Case 2: Event Study Aggregations
Next, we consider event study aggregations. The first is an event study aggregation for `ATT`. The second is an event study aggregation for `ACRT`.
**Event study aggregation for `ATT`:**
Notice that the target parameter is set `level` to target ATT, and the `aggregation` argument is set to `eventstudy`.
```{r, warning=FALSE, message=FALSE}
cd_res_es_level <- cont_did(
yname = "Y",
tname = "time_period",
idname = "id",
dname = "D",
data = df,
gname = "G",
target_parameter = "level",
aggregation = "eventstudy",
treatment_type = "continuous",
control_group = "notyettreated",
biters = 100,
cband = TRUE,
num_knots = 1,
degree = 3,
)
summary(cd_res_es_level)
ggcont_did(cd_res_es_level)
```
**Event study aggregation for `ACRT`:**
Relative to the previous code, notice that the target parameter is set `slope` to target ACRT.
```{r, warning=FALSE, message=FALSE}
cd_res_es_slope <- cont_did(
yname = "Y",
tname = "time_period",
idname = "id",
dname = "D",
data = df,
gname = "G",
target_parameter = "slope",
aggregation = "eventstudy",
treatment_type = "continuous",
control_group = "notyettreated",
biters = 100,
cband = TRUE,
num_knots = 1,
degree = 3,
)
summary(cd_res_es_slope)
ggcont_did(cd_res_es_slope)
```
### Case 3: Data-Driven Nonparametric Model for Treatment Effects
In most applications, it is hard to know the correct functional form for the treatment effects as a function of the dose. In @callaway-goodman-santanna-2025, the approach we emphasize comes from @chen-christensen-kankanala-2025, and the `contdid` package uses their [`npiv` package](https://github.com/JeffreyRacine/npiv) to implement this approach. Code-wise, the only thing to change is to set the argument `dose_est_method="cck"`. [Note that we currently only support this option for the case with two periods and no staggered adoption. With more periods, you can average the pre- and post-treatment periods to reduce it to a two period case and then run the code below; in fact, this is what we did in the application in our paper.]
```{r, warning=FALSE, message=FALSE, cache=TRUE}
# simulate data with only two periods
# add quadratic effect to see how well we can detect it
# (note code will not "know" that the effect is quadratic)
df2 <- simulate_contdid_data(
n = 5000,
num_time_periods = 2,
num_groups = 2,
dose_linear_effect = 0,
dose_quadratic_effect = 1
)
df2$D[df2$G == 0] <- 0
head(df2)
cd_res_cck <- cont_did(
yname = "Y",
tname = "time_period",
idname = "id",
dname = "D",
data = df2,
gname = "G",
target_parameter = "level",
aggregation = "dose",
treatment_type = "continuous",
dose_est_method = "cck",
control_group = "notyettreated",
biters = 100,
cband = TRUE,
)
summary(cd_res_cck)
ggcont_did(cd_res_cck) +
stat_function(
fun = function(x) x^2,
aes(color = "Truth"),
linetype = "dashed",
size = 1
) +
scale_color_manual(values = c("Truth" = "red")) +
labs(color = "")
```
## References
Owner
- Login: bcallaway11
- Kind: user
- Location: Athens, GA
- Company: University of Georgia
- Website: www.brantlycallaway.com
- Repositories: 23
- Profile: https://github.com/bcallaway11
Brantly Callaway, Department of Economics, University of Georgia
Citation (CITATION.cff)
# --------------------------------------------
# CITATION file created with {cffr} R package
# See also: https://docs.ropensci.org/cffr/
# --------------------------------------------
cff-version: 1.2.0
message: 'To cite package "contdid" in publications use:'
type: software
license: GPL-3.0-only
title: 'contdid: Difference-in-Differences with a Continuous Treatment'
version: 0.1.0
abstract: Provides methods for difference-in-differences with a continuous treatment
and staggered treatment adoption. Includes estimation of treatment effects and causal
responses as a function of the dose, event studies indexed by length of exposure
to the treatment, and aggregation into overall average effects. Uniform inference
procedures are included, along with both parametric and nonparametric models for
treatment effects. The methods are based on Callaway, Goodman-Bacon, and Sant'Anna
(2025) <https://doi.org/10.48550/arXiv.2107.02637>.
authors:
- family-names: Callaway
given-names: Brantly
email: brantly.callaway@uga.edu
- family-names: Goodman-Bacon
given-names: Andrew
email: andrew@goodman-bacon.com
- family-names: Sant'Anna
given-names: Pedro H. C.
email: pedro.h.santanna@emory.edu
preferred-citation:
type: manual
title: Difference-in-Differences with a Continuous Treatment
authors:
- family-names: Callaway
given-names: Brantly
email: brantly.callaway@uga.edu
- family-names: Goodman-Bacon
given-names: Andrew
email: andrew@goodman-bacon.com
- family-names: Sant'Anna
given-names: Pedro H. C.
email: pedro.h.santanna@emory.edu
year: '2025'
notes: R package version 0.1.0
url: https://bcallaway11.github.io/contdid/
repository-code: https://github.com/bcallaway11/contdid
url: https://bcallaway11.github.io/contdid/
contact:
- family-names: Callaway
given-names: Brantly
email: brantly.callaway@uga.edu
references:
- type: software
title: 'R: A Language and Environment for Statistical Computing'
notes: Depends
url: https://www.R-project.org/
authors:
- name: R Core Team
institution:
name: R Foundation for Statistical Computing
address: Vienna, Austria
year: '2025'
version: '>= 4.1.0'
- type: software
title: MASS
abstract: 'MASS: Support Functions and Datasets for Venables and Ripley''s MASS'
notes: Imports
url: http://www.stats.ox.ac.uk/pub/MASS4/
repository: https://CRAN.R-project.org/package=MASS
authors:
- family-names: Ripley
given-names: Brian
email: Brian.Ripley@R-project.org
- family-names: Venables
given-names: Bill
year: '2025'
doi: 10.32614/CRAN.package.MASS
GitHub Events
Total
- Issues event: 6
- Watch event: 22
- Issue comment event: 8
- Push event: 13
- Pull request event: 2
- Fork event: 2
Last Year
- Issues event: 6
- Watch event: 22
- Issue comment event: 8
- Push event: 13
- Pull request event: 2
- Fork event: 2
Issues and Pull Requests
Last synced: 6 months ago
All Time
- Total issues: 6
- Total pull requests: 2
- Average time to close issues: 3 days
- Average time to close pull requests: 9 minutes
- Total issue authors: 5
- Total pull request authors: 1
- Average comments per issue: 2.67
- Average comments per pull request: 0.0
- Merged pull requests: 2
- Bot issues: 0
- Bot pull requests: 0
Past Year
- Issues: 6
- Pull requests: 2
- Average time to close issues: 3 days
- Average time to close pull requests: 9 minutes
- Issue authors: 5
- Pull request authors: 1
- Average comments per issue: 2.67
- Average comments per pull request: 0.0
- Merged pull requests: 2
- Bot issues: 0
- Bot pull requests: 0
Top Authors
Issue Authors
- skuchukh (2)
- EddieLUO97 (1)
- btleyden (1)
- economistrosa (1)
- ser1c (1)
Pull Request Authors
- pedrohcgs (2)
Top Labels
Issue Labels
Pull Request Labels
Packages
- Total packages: 1
-
Total downloads:
- cran 168 last-month
- Total dependent packages: 0
- Total dependent repositories: 0
- Total versions: 1
- Total maintainers: 1
cran.r-project.org: contdid
Difference-in-Differences with a Continuous Treatment
- Homepage: https://bcallaway11.github.io/contdid/
- Documentation: http://cran.r-project.org/web/packages/contdid/contdid.pdf
- License: GPL-3
-
Latest release: 0.1.0
published 8 months ago
Rankings
Stargazers count: 12.9%
Forks count: 17.3%
Dependent packages count: 26.1%
Dependent repos count: 32.2%
Average: 35.0%
Downloads: 86.4%
Maintainers (1)
Last synced:
6 months ago
Dependencies
.github/workflows/check-package.yml
actions
- actions/checkout v4 composite
- actions/upload-artifact v4 composite
- r-lib/actions/setup-r v2 composite
.github/workflows/revdep-check-test.yml
actions
- actions/checkout v4 composite
- actions/upload-artifact v4 composite
- r-lib/actions/setup-r v2 composite
.github/workflows/update-citation.yml
actions
- actions/checkout v4 composite
- r-lib/actions/setup-r v2 composite
DESCRIPTION
cran
- R >= 4.1.0 depends
- BMisc >= 1.4.8 imports
- MASS * imports
- checkmate * imports
- ggplot2 * imports
- npiv * imports
- ptetools * imports
- sandwich * imports
- splines2 * imports
- testthat >= 3.0.0 suggests
- tidyr * suggests