diff --git a/R/honest_sunab.R b/R/honest_sunab.R new file mode 100644 index 0000000..4d82fce --- /dev/null +++ b/R/honest_sunab.R @@ -0,0 +1,36 @@ +#' @description +#' This function takes a regression estimated using fixest with the sunab option +#' and extracts the aggregated event-study coefficients and their variance-covariance matrix +#' @param sunab_fixest The result of a fixest call using the sunab option +#' @returns A list containing beta (the event-study coefficients), +#' sigma (the variance-covariance matrix), and +#' cohorts (the relative times corresponding to beta, sigma) + +sunab_beta_vcv <- +function(sunab_fixest){ + + ## The following code block extracts the weights on individual coefs used in + # the fixest aggregation ## + sunab_agg <- sunab_fixest$model_matrix_info$sunab$agg_period + sunab_names <- names(sunab_fixest$coefficients) + sunab_sel <- grepl(sunab_agg, sunab_names, perl=TRUE) + sunab_names <- sunab_names[sunab_sel] + if(!is.null(sunab_fixest$weights)){ + sunab_wgt <- colSums(sunab_fixest$weights * sign(model.matrix(sunab_fixest)[, sunab_names, drop=FALSE])) + } else { + sunab_wgt <- colSums(sign(model.matrix(sunab_fixest)[, sunab_names, drop=FALSE])) + } + + #Construct matrix sunab_trans such that sunab_trans %*% non-aggregated coefs = aggregated coefs, + sunab_cohorts <- as.numeric(gsub(paste0(".*", sunab_agg, ".*"), "\\2", sunab_names, perl=TRUE)) + sunab_mat <- model.matrix(~ 0 + factor(sunab_cohorts)) + sunab_trans <- solve(t(sunab_mat) %*% (sunab_wgt * sunab_mat)) %*% t(sunab_wgt * sunab_mat) + + #Get the coefs and vcv + sunab_coefs <- sunab_trans %*% cbind(sunab_fixest$coefficients[sunab_sel]) + sunab_vcov <- sunab_trans %*% sunab_fixest$cov.scaled[sunab_sel, sunab_sel] %*% t(sunab_trans) + + return(list(beta = sunab_coefs, + sigma = sunab_vcov, + cohorts = sort(unique(sunab_cohorts)))) +} diff --git a/README.Rmd b/README.Rmd index ab520bb..ffeef44 100644 --- a/README.Rmd +++ b/README.Rmd @@ -12,32 +12,32 @@ The HonestDiD R package implements the tools for robust inference and sensitivit ## Background -The robust inference approach in Rambachan and Roth formalizes the intuition that pre-trends are informative about violations of parallel trends. They provide a few different ways of formalizing what this means. +The robust inference approach in Rambachan and Roth formalizes the intuition that pre-trends are informative about violations of parallel trends. They provide a few different ways of formalizing what this means. -**Bounds on relative magnitudes.** One way of formalizing this idea is to say that the violations of parallel trends in the post-treatment period cannot be much bigger than those in the pre-treatment period. This can be formalized by imposing that the post-treatment violation of parallel trends is no more than some constant larger than the maximum violation of parallel trends in the pre-treatment period. The value of = 1, for instance, imposes that the post-treatment violation of parallel trends is no longer than the worst pre-treatment violation of parallel trends (between consecutive periods). Likewise, setting = 2 implies that the post-treatment violation of parallel trends is no more than twice that in the pre-treatment period. +**Bounds on relative magnitudes.** One way of formalizing this idea is to say that the violations of parallel trends in the post-treatment period cannot be much bigger than those in the pre-treatment period. This can be formalized by imposing that the post-treatment violation of parallel trends is no more than some constant larger than the maximum violation of parallel trends in the pre-treatment period. The value of = 1, for instance, imposes that the post-treatment violation of parallel trends is no longer than the worst pre-treatment violation of parallel trends (between consecutive periods). Likewise, setting = 2 implies that the post-treatment violation of parallel trends is no more than twice that in the pre-treatment period. **Smoothness restrictions.** A second way of formalizing this is to say that the post-treatment violations of parallel trends cannot deviate too much from a linear extrapolation of the pre-trend. In particular, we can impose that the slope of the pre-trend can change by no more than *M* across consecutive periods, as shown in the figure below for an example with three periods. ![diagram-smoothness-restriction](deltaSD.png) -Thus, imposing a smoothness restriction with *M* = 0 implies that the counterfactual difference in trends is exactly linear, whereas larger values of *M* allow for more non-linearity. +Thus, imposing a smoothness restriction with *M* = 0 implies that the counterfactual difference in trends is exactly linear, whereas larger values of *M* allow for more non-linearity. -**Other restrictions**. The Rambachan and Roth framework allows for a variety of other restrictions on the differences in trends as well. For example, the smoothness restrictions and relative magnitudes ideas can be combined to impose that the non-linearity in the post-treatment period is no more than times larger than that in the pre-treatment periods. The researcher can also impose monotonicity or sign restrictions on the differences in trends as well. +**Other restrictions**. The Rambachan and Roth framework allows for a variety of other restrictions on the differences in trends as well. For example, the smoothness restrictions and relative magnitudes ideas can be combined to impose that the non-linearity in the post-treatment period is no more than times larger than that in the pre-treatment periods. The researcher can also impose monotonicity or sign restrictions on the differences in trends as well. **Robust confidence intervals**. Given restrictions of the type described above, Rambachan and Roth provide methods for creating robust confidence intervals that are guaranteed to include the true parameter at least 95% of the time when the imposed restrictions on satisfied. These confidence intervals account for the fact that there is estimation error both in the treatment effects estimates and our estimates of the pre-trends. -**Sensitivity analysis**. The approach described above naturally lends itself to sensitivity analysis. That is, the researcher can report confidence intervals under different assumptions about how bad the post-treatment violation of parallel trends can be (e.g., different values of or *M*.) They can also report the "breakdown value" of (or *M*) for a particular conclusion -- e.g. the largest value of for which the effect is still significant. +**Sensitivity analysis**. The approach described above naturally lends itself to sensitivity analysis. That is, the researcher can report confidence intervals under different assumptions about how bad the post-treatment violation of parallel trends can be (e.g., different values of or *M*.) They can also report the "breakdown value" of (or *M*) for a particular conclusion -- e.g. the largest value of for which the effect is still significant. -## Package installation +## Package installation The package may be installed by using the function `install_github()` from the `remotes` package: ```{r,eval = FALSE} ## Installation # Install remotes package if not installed -install.packages("remotes") +install.packages("remotes") # Turn off warning-error-conversion, because the tiniest warning stops installation Sys.setenv("R_REMOTES_NO_ERRORS_FROM_WARNINGS" = "true") @@ -50,7 +50,7 @@ remotes::install_github("asheshrambachan/HonestDiD") ## Example usage -- Medicaid expansions -As an illustration of the package, we will examine the effects of Medicaid expansions on insurance coverage using publicly-available data derived from the ACS. We first load the data and packages relevant for the analysis. +As an illustration of the package, we will examine the effects of Medicaid expansions on insurance coverage using publicly-available data derived from the ACS. We first load the data and packages relevant for the analysis. ```{r, message = F, warning=F} @@ -73,7 +73,7 @@ The data is a state-level panel with information on health insurance coverage an ### Estimate the baseline DiD -For simplicity, we will first focus on assessing sensitivity to violations of parallel trends in a non-staggered DiD (see below regarding methods for staggered timing). We therefore restrict the sample to the years 2015 and earlier, and drop the small number of states who are first treated in 2015. We are now left with a panel dataset where some units are first treated in 2014 and the remaining units are not treated during the sample period. We can then estimate the effects of Medicaid expansion using a canonical two-way fixed effects event-study specification, +For simplicity, we will first focus on assessing sensitivity to violations of parallel trends in a non-staggered DiD (see below regarding methods for staggered timing). We therefore restrict the sample to the years 2015 and earlier, and drop the small number of states who are first treated in 2015. We are now left with a panel dataset where some units are first treated in 2014 and the remaining units are not treated during the sample period. We can then estimate the effects of Medicaid expansion using a canonical two-way fixed effects event-study specification, @@ -84,15 +84,15 @@ where D is 1 if a unit is first treated in 2014 and 0 otherwise. df <- read_dta("https://raw.githubusercontent.com/Mixtape-Sessions/Advanced-DID/main/Exercises/Data/ehec_data.dta") #Keep years before 2016. Drop the 2016 cohort -df_nonstaggered <- df %>% filter(year < 2016 & +df_nonstaggered <- df %>% filter(year < 2016 & (is.na(yexp2)| yexp2 != 2015) ) #Create a treatment dummy df_nonstaggered <- df_nonstaggered %>% mutate(D = case_when( yexp2 == 2014 ~ 1, - T ~ 0)) + T ~ 0)) #Run the TWFE spec -twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) | stfips + year, +twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) | stfips + year, cluster = "stfips", data = df_nonstaggered) @@ -110,10 +110,10 @@ fixest::iplot(twfe_results) ## Sensitivity analysis using relative magnitudes restrictions -We are now ready to apply the HonestDiD package to do sensitivity analysis. Suppose we're interested in assessing the sensitivity of the estimate for 2014, the first year after treatment. +We are now ready to apply the HonestDiD package to do sensitivity analysis. Suppose we're interested in assessing the sensitivity of the estimate for 2014, the first year after treatment. ```{r, cache = TRUE, warning=FALSE} -delta_rm_results <- +delta_rm_results <- HonestDiD::createSensitivityResults_relativeMagnitudes( betahat = betahat, #coefficients sigma = sigma, #covariance matrix @@ -126,9 +126,9 @@ delta_rm_results ``` -The output of the previous command shows a robust confidence interval for different values of . We see that the "breakdown value" for a significant effect is = 2, meaning that the significant result is robust to allowing for violations of parallel trends up to twice as big as the max violation in the pre-treatment period. +The output of the previous command shows a robust confidence interval for different values of . We see that the "breakdown value" for a significant effect is = 2, meaning that the significant result is robust to allowing for violations of parallel trends up to twice as big as the max violation in the pre-treatment period. -We can also visualize the sensitivity analysis using the `createSensitivityPlot_relativeMagnitudes`. To do this, we first have to calculate the CI for the original OLS estimates using the `constructOriginalCS` command. We then pass our sensitivity analysis and the original results to the `createSensitivityPlot_relativeMagnitudes` command. +We can also visualize the sensitivity analysis using the `createSensitivityPlot_relativeMagnitudes`. To do this, we first have to calculate the CI for the original OLS estimates using the `constructOriginalCS` command. We then pass our sensitivity analysis and the original results to the `createSensitivityPlot_relativeMagnitudes` command. ```{r} originalResults <- HonestDiD::constructOriginalCS(betahat = betahat, @@ -141,9 +141,9 @@ HonestDiD::createSensitivityPlot_relativeMagnitudes(delta_rm_results, originalRe ## Sensitivity Analysis Using Smoothness Restrictions -We can also do a sensitivity analysis based on smoothness restrictions -- i.e. imposing that the slope of the difference in trends changes by no more than *M* between periods. +We can also do a sensitivity analysis based on smoothness restrictions -- i.e. imposing that the slope of the difference in trends changes by no more than *M* between periods. ```{r, cache=TRUE} -delta_sd_results <- +delta_sd_results <- HonestDiD::createSensitivityResults(betahat = betahat, sigma = sigma, numPrePeriods = 5, @@ -158,10 +158,10 @@ We see that the breakdown value for a significant effect is *M* ≈ 0.03, me ## Sensitivity Analysis for Average Effects or Other Periods -So far we have focused on the effect for the first post-treatment period, which is the default in HonestDiD. If we are instead interested in the average over the two post-treatment periods, we can use the option `l_vec = c(0.5,0.5)`. More generally, the package accommodates inference on any scalar parameter of the form *θ* = *l**v**e**c*′*τ**p**o**s**t*, where *τ**p**o**s**t* = (*τ*1,...,*τ**T̄*)′ is the vector of dynamic treatment effects. Thus, for example, setting `l_vec = basisVector(2,numPostPeriods)` allows us to do inference on the effect for the second period after treatment. +So far we have focused on the effect for the first post-treatment period, which is the default in HonestDiD. If we are instead interested in the average over the two post-treatment periods, we can use the option `l_vec = c(0.5,0.5)`. More generally, the package accommodates inference on any scalar parameter of the form *θ* = *l**v**e**c*′*τ**p**o**s**t*, where *τ**p**o**s**t* = (*τ*1,...,*τ**T̄*)′ is the vector of dynamic treatment effects. Thus, for example, setting `l_vec = basisVector(2,numPostPeriods)` allows us to do inference on the effect for the second period after treatment. ```{r, cache=TRUE} -delta_rm_results_avg <- +delta_rm_results_avg <- HonestDiD::createSensitivityResults_relativeMagnitudes(betahat = betahat, sigma = sigma, numPrePeriods = 5, @@ -179,7 +179,7 @@ HonestDiD::createSensitivityPlot_relativeMagnitudes(delta_rm_results_avg, origin ## Regressions with controls -The parameters `betahat` and `sigma` should be the coefficients and variance-covariance matrix for the **event-study** plot only. Sometimes we may have regression results that contain both the event-study coefficients and coefficients on other auxilliary variables (e.g. controls). In this case, we should subset `betahat` and `sigma` to the relevant coefficients corresponding to the event-study. An example is given below: +The parameters `betahat` and `sigma` should be the coefficients and variance-covariance matrix for the **event-study** plot only. Sometimes we may have regression results that contain both the event-study coefficients and coefficients on other auxilliary variables (e.g. controls). In this case, we should subset `betahat` and `sigma` to the relevant coefficients corresponding to the event-study. An example is given below: ```{r, cache=T} @@ -189,7 +189,7 @@ df_nonstaggered$control <- rnorm(NROW(df_nonstaggered), 0, 1) #Run the TWFE spec with the control added # (Note that TWFEs with controls may not yield ATT under het effects; see Abadie 2005) -twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) + control | stfips + year, +twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) + control | stfips + year, cluster = "stfips", data = df_nonstaggered) @@ -210,7 +210,44 @@ HonestDiD::createSensitivityResults(betahat = betahat, ## Staggered timing -So far we have focused on a simple case without staggered timing. Fortunately, the HonestDiD approach works well with recently-introduced methods for DiD under staggered treatment timing. Below, we show how the package can be used with the [did package](https://github.com/bcallaway11/did#difference-in-differences-) implementing Callaway and Sant'Anna. (See, also, the example on the did package [website](https://github.com/pedrohcgs/CS_RR)). We are hoping to more formally integrate the did and HonestDiD packages in the future -- stay tuned! +So far we have focused on a simple case without staggered timing. Fortunately, the HonestDiD approach works well with recently-introduced methods for DiD under staggered treatment timing. Below, we show how the package can be used with the [fixest package](https://lrberge.github.io/fixest/reference/sunab.html) implementing Sun and Abraham or with the [did package](https://github.com/bcallaway11/did#difference-in-differences-) implementing Callaway and Sant'Anna. (See, also, the example on the did package [website](https://github.com/pedrohcgs/CS_RR).) We are hoping to more formally integrate the did and HonestDiD packages in the future -- stay tuned! + +### Sun and Abraham + +First, we import the function we created for extracting the full-variance covariance matrix from `fixest` with `sunab`: + +```{r, code = readLines("R/honest_sunab.R")} +``` + +```{r, cache = TRUE} +# Run fixest with sunab +df$year_treated <- ifelse(is.na(df$yexp2), Inf, df$yexp2) +formula_sunab <- dins ~ sunab(year_treated, year) | stfips + year +res_sunab <- fixest::feols(formula_sunab, cluster="stfips", data=df) +fixest::iplot(res_sunab) + +# Extract the beta and vcv +beta_vcv <- sunab_beta_vcv(res_sunab) + +# Run sensitivity analysis for relative magnitudes +kwargs <- list(betahat = beta_vcv$beta, + sigma = beta_vcv$sigma, + numPrePeriods = sum(beta_vcv$cohorts < 0), + numPostPeriods = sum(beta_vcv$cohorts > -1)) +extra <- list(Mbarvec=seq(from = 0.5, to = 2, by = 0.5), gridPoints=100) + +original_results <- + do.call(HonestDiD::constructOriginalCS, kwargs) + +sensitivity_results <- + do.call(HonestDiD::createSensitivityResults_relativeMagnitudes, + c(kwargs, extra)) + +HonestDiD::createSensitivityPlot_relativeMagnitudes(sensitivity_results, + original_results) +``` + +### Callaway and Sant'Anna First, we import the function Pedro Sant'Anna created for formatting did output for HonestDiD: @@ -223,16 +260,16 @@ First, we import the function Pedro Sant'Anna created for formatting did output ## Note that universal base period normalizes the event-time minus 1 coef to 0 cs_results <- did::att_gt(yname = "dins", tname = "year", - idname = "stfips", - gname = "yexp2", + idname = "stfips", + gname = "yexp2", data = df %>% mutate(yexp2 = ifelse(is.na(yexp2), 3000, yexp2)), control_group = "notyettreated", base_period = "universal") -es <- did::aggte(cs_results, type = "dynamic", +es <- did::aggte(cs_results, type = "dynamic", min_e = -5, max_e = 5) -#Run sensitivity analysis for relative magnitudes +#Run sensitivity analysis for relative magnitudes sensitivity_results <- honest_did(es, e=0, @@ -246,7 +283,7 @@ HonestDiD::createSensitivityPlot_relativeMagnitudes(sensitivity_results$robust_c ## Additional options and resources -See the previous package [vignette] for additional examples and package options, including incorporating sign and monotonicity restrictions, and combining relative magnitudes and smoothness restrictions. +See the previous package [vignette] for additional examples and package options, including incorporating sign and monotonicity restrictions, and combining relative magnitudes and smoothness restrictions. You can also view a video presentation about this paper [here](https://www.youtube.com/watch?v=6-NkiA2jN7U). diff --git a/README.md b/README.md index 1afbcb7..41a32de 100644 --- a/README.md +++ b/README.md @@ -89,7 +89,7 @@ from the `remotes` package: ## Installation # Install remotes package if not installed -install.packages("remotes") +install.packages("remotes") # Turn off warning-error-conversion, because the tiniest warning stops installation Sys.setenv("R_REMOTES_NO_ERRORS_FROM_WARNINGS" = "true") @@ -157,15 +157,15 @@ where D is 1 if a unit is first treated in 2014 and 0 otherwise. df <- read_dta("https://raw.githubusercontent.com/Mixtape-Sessions/Advanced-DID/main/Exercises/Data/ehec_data.dta") #Keep years before 2016. Drop the 2016 cohort -df_nonstaggered <- df %>% filter(year < 2016 & +df_nonstaggered <- df %>% filter(year < 2016 & (is.na(yexp2)| yexp2 != 2015) ) #Create a treatment dummy df_nonstaggered <- df_nonstaggered %>% mutate(D = case_when( yexp2 == 2014 ~ 1, - T ~ 0)) + T ~ 0)) #Run the TWFE spec -twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) | stfips + year, +twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) | stfips + year, cluster = "stfips", data = df_nonstaggered) @@ -186,7 +186,7 @@ analysis. Suppose we’re interested in assessing the sensitivity of the estimate for 2014, the first year after treatment. ``` r -delta_rm_results <- +delta_rm_results <- HonestDiD::createSensitivityResults_relativeMagnitudes( betahat = betahat, #coefficients sigma = sigma, #covariance matrix @@ -199,12 +199,12 @@ delta_rm_results ``` ## # A tibble: 4 × 5 - ## lb ub method Delta Mbar - ## - ## 1 0.0240 0.0672 C-LF DeltaRM 0.5 - ## 2 0.0170 0.0720 C-LF DeltaRM 1 - ## 3 0.00824 0.0797 C-LF DeltaRM 1.5 - ## 4 -0.000916 0.0881 C-LF DeltaRM 2 + ## lb ub method Delta Mbar + ## + ## 1 0.0241 0.0673 C-LF DeltaRM 0.5 + ## 2 0.0171 0.0720 C-LF DeltaRM 1 + ## 3 0.00859 0.0796 C-LF DeltaRM 1.5 + ## 4 -0.00107 0.0883 C-LF DeltaRM 2 The output of the previous command shows a robust confidence interval for different values of @@ -240,7 +240,7 @@ i.e. imposing that the slope of the difference in trends changes by no more than *M* between periods. ``` r -delta_sd_results <- +delta_sd_results <- HonestDiD::createSensitivityResults(betahat = betahat, sigma = sigma, numPrePeriods = 5, @@ -285,7 +285,7 @@ the vector of dynamic treatment effects. Thus, for example, setting effect for the second period after treatment. ``` r -delta_rm_results_avg <- +delta_rm_results_avg <- HonestDiD::createSensitivityResults_relativeMagnitudes(betahat = betahat, sigma = sigma, numPrePeriods = 5, @@ -320,7 +320,7 @@ df_nonstaggered$control <- rnorm(NROW(df_nonstaggered), 0, 1) #Run the TWFE spec with the control added # (Note that TWFEs with controls may not yield ATT under het effects; see Abadie 2005) -twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) + control | stfips + year, +twfe_results <- fixest::feols(dins ~ i(year, D, ref = 2013) + control | stfips + year, cluster = "stfips", data = df_nonstaggered) @@ -354,13 +354,95 @@ HonestDiD::createSensitivityResults(betahat = betahat, So far we have focused on a simple case without staggered timing. Fortunately, the HonestDiD approach works well with recently-introduced methods for DiD under staggered treatment timing. Below, we show how the -package can be used with the [did +package can be used with the [fixest +package](https://lrberge.github.io/fixest/reference/sunab.html) +implementing Sun and Abraham or with the [did package](https://github.com/bcallaway11/did#difference-in-differences-) implementing Callaway and Sant’Anna. (See, also, the example on the did -package [website](https://github.com/pedrohcgs/CS_RR)). We are hoping to +package [website](https://github.com/pedrohcgs/CS_RR).) We are hoping to more formally integrate the did and HonestDiD packages in the future – stay tuned! +### Sun and Abraham + +First, we import the function we created for extracting the +full-variance covariance matrix from `fixest` with `sunab`: + +``` r +#' @description +#' This function takes a regression estimated using fixest with the sunab option +#' and extracts the aggregated event-study coefficients and their variance-covariance matrix +#' @param sunab_fixest The result of a fixest call using the sunab option +#' @returns A list containing beta (the event-study coefficients), +#' sigma (the variance-covariance matrix), and +#' cohorts (the relative times corresponding to beta, sigma) + +sunab_beta_vcv <- +function(sunab_fixest){ + + ## The following code block extracts the weights on individual coefs used in + # the fixest aggregation ## + sunab_agg <- sunab_fixest$model_matrix_info$sunab$agg_period + sunab_names <- names(sunab_fixest$coefficients) + sunab_sel <- grepl(sunab_agg, sunab_names, perl=TRUE) + sunab_names <- sunab_names[sunab_sel] + if(!is.null(sunab_fixest$weights)){ + sunab_wgt <- colSums(sunab_fixest$weights * sign(model.matrix(sunab_fixest)[, sunab_names, drop=FALSE])) + } else { + sunab_wgt <- colSums(sign(model.matrix(sunab_fixest)[, sunab_names, drop=FALSE])) + } + + #Construct matrix sunab_trans such that sunab_trans %*% non-aggregated coefs = aggregated coefs, + sunab_cohorts <- as.numeric(gsub(paste0(".*", sunab_agg, ".*"), "\\2", sunab_names, perl=TRUE)) + sunab_mat <- model.matrix(~ 0 + factor(sunab_cohorts)) + sunab_trans <- solve(t(sunab_mat) %*% (sunab_wgt * sunab_mat)) %*% t(sunab_wgt * sunab_mat) + + #Get the coefs and vcv + sunab_coefs <- sunab_trans %*% cbind(sunab_fixest$coefficients[sunab_sel]) + sunab_vcov <- sunab_trans %*% sunab_fixest$cov.scaled[sunab_sel, sunab_sel] %*% t(sunab_trans) + + return(list(beta = sunab_coefs, + sigma = sunab_vcov, + cohorts = sort(unique(sunab_cohorts)))) +} +``` + +``` r +# Run fixest with sunab +df$year_treated <- ifelse(is.na(df$yexp2), Inf, df$yexp2) +formula_sunab <- dins ~ sunab(year_treated, year) | stfips + year +res_sunab <- fixest::feols(formula_sunab, cluster="stfips", data=df) +fixest::iplot(res_sunab) +``` + +![](README_files/figure-gfm/unnamed-chunk-10-1.png) + +``` r +# Extract the beta and vcv +beta_vcv <- sunab_beta_vcv(res_sunab) + +# Run sensitivity analysis for relative magnitudes +kwargs <- list(betahat = beta_vcv$beta, + sigma = beta_vcv$sigma, + numPrePeriods = sum(beta_vcv$cohorts < 0), + numPostPeriods = sum(beta_vcv$cohorts > -1)) +extra <- list(Mbarvec=seq(from = 0.5, to = 2, by = 0.5), gridPoints=100) + +original_results <- + do.call(HonestDiD::constructOriginalCS, kwargs) + +sensitivity_results <- + do.call(HonestDiD::createSensitivityResults_relativeMagnitudes, + c(kwargs, extra)) + +HonestDiD::createSensitivityPlot_relativeMagnitudes(sensitivity_results, + original_results) +``` + +![](README_files/figure-gfm/unnamed-chunk-10-2.png) + +### Callaway and Sant’Anna + First, we import the function Pedro Sant’Anna created for formatting did output for HonestDiD: @@ -369,6 +451,8 @@ output for HonestDiD: #' #' @description a function to compute a sensitivity analysis #' using the approach of Rambachan and Roth (2021) +#' +#' @param ... Parameters to pass to the relevant method. honest_did <- function(...) UseMethod("honest_did") #' @title honest_did.AGGTEobj @@ -377,6 +461,7 @@ honest_did <- function(...) UseMethod("honest_did") #' using the approach of Rambachan and Roth (2021) when #' the event study is estimating using the `did` package #' +#' @param es Result from aggte (object of class AGGTEobj). #' @param e event time to compute the sensitivity analysis for. #' The default value is `e=0` corresponding to the "on impact" #' effect of participating in the treatment. @@ -385,6 +470,11 @@ honest_did <- function(...) UseMethod("honest_did") #' in pre-treatment periods) or "relative_magnitude" (which #' conducts a sensitivity analysis based on the relative magnitudes #' of deviations from parallel trends in pre-treatment periods). +#' @param gridPoints Number of grid points used for the underlying test +#' inversion. Default equals 100. User may wish to change the number of grid +#' points for computational reasons. +#' @param ... Parameters to pass to `createSensitivityResults` or +#' `createSensitivityResults_relativeMagnitudes`. #' @inheritParams HonestDiD::createSensitivityResults #' @inheritParams HonestDid::createSensitivityResults_relativeMagnitudes honest_did.AGGTEobj <- function(es, @@ -480,16 +570,16 @@ honest_did.AGGTEobj <- function(es, ## Note that universal base period normalizes the event-time minus 1 coef to 0 cs_results <- did::att_gt(yname = "dins", tname = "year", - idname = "stfips", - gname = "yexp2", + idname = "stfips", + gname = "yexp2", data = df %>% mutate(yexp2 = ifelse(is.na(yexp2), 3000, yexp2)), control_group = "notyettreated", base_period = "universal") -es <- did::aggte(cs_results, type = "dynamic", +es <- did::aggte(cs_results, type = "dynamic", min_e = -5, max_e = 5) -#Run sensitivity analysis for relative magnitudes +#Run sensitivity analysis for relative magnitudes sensitivity_results <- honest_did(es, e=0, @@ -500,7 +590,7 @@ HonestDiD::createSensitivityPlot_relativeMagnitudes(sensitivity_results$robust_c sensitivity_results$orig_ci) ``` -![](README_files/figure-gfm/unnamed-chunk-10-1.png) +![](README_files/figure-gfm/unnamed-chunk-12-1.png) ## Additional options and resources diff --git a/README_cache/gfm/__packages b/README_cache/gfm/__packages index 64af45c..084c9e4 100644 --- a/README_cache/gfm/__packages +++ b/README_cache/gfm/__packages @@ -21,4 +21,3 @@ forcats TruncatedNormal HonestDiD fixest -base diff --git a/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.RData b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.RData new file mode 100644 index 0000000..91be6b9 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.RData differ diff --git a/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdb b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdb new file mode 100644 index 0000000..6e71b87 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdx b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdx new file mode 100644 index 0000000..09b47d5 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-10_1f3c743ec6ce57aeac2e128cd86dc961.rdx differ diff --git a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.RData b/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.RData deleted file mode 100644 index 1d5b913..0000000 Binary files a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.RData and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdb b/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdb deleted file mode 100644 index c1aa1a5..0000000 Binary files a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdb and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdx b/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdx deleted file mode 100644 index 055e397..0000000 Binary files a/README_cache/gfm/unnamed-chunk-10_ecab2df8a730e51bf3ade706308e54c6.rdx and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.RData b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.RData new file mode 100644 index 0000000..7ef3521 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.RData differ diff --git a/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdb b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdb new file mode 100644 index 0000000..dc667cd Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdx b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdx new file mode 100644 index 0000000..687d53e Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-12_72f0b4e078ccf5be9960c1babb518ff3.rdx differ diff --git a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.RData b/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.RData deleted file mode 100644 index 2831b74..0000000 Binary files a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.RData and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdb b/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdb deleted file mode 100644 index 5ead1a1..0000000 Binary files a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdb and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdx b/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdx deleted file mode 100644 index 86e5bf1..0000000 Binary files a/README_cache/gfm/unnamed-chunk-4_787f5d4d7640d5f64b3f8c7dba3b50b2.rdx and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.RData b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.RData new file mode 100644 index 0000000..fcd5ec9 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.RData differ diff --git a/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdb b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdb new file mode 100644 index 0000000..77c5b53 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdx b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdx new file mode 100644 index 0000000..08e18c5 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-4_d08e39374736e71fa1379f8379b56bb5.rdx differ diff --git a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.RData b/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.RData deleted file mode 100644 index e672afd..0000000 Binary files a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.RData and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdb b/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdb deleted file mode 100644 index 1ad196b..0000000 Binary files a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdb and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdx b/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdx deleted file mode 100644 index 34d1367..0000000 Binary files a/README_cache/gfm/unnamed-chunk-6_4277bfb509c005afc3529900c5e17d65.rdx and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.RData b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.RData new file mode 100644 index 0000000..dfb420d Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.RData differ diff --git a/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdb b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdb new file mode 100644 index 0000000..c2bcb4f Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdx b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdx new file mode 100644 index 0000000..ff802cf Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-6_6a1a19c1b25737f3167f0bb30e5b250d.rdx differ diff --git a/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.RData b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.RData new file mode 100644 index 0000000..3cebfd7 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.RData differ diff --git a/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdb b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdb new file mode 100644 index 0000000..c61de05 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdx b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdx new file mode 100644 index 0000000..0c765cd Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-7_40d31aed1b8b0bc2d595204b6c288837.rdx differ diff --git a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.RData b/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.RData deleted file mode 100644 index 1f9fe3e..0000000 Binary files a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.RData and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdb b/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdb deleted file mode 100644 index e043814..0000000 Binary files a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdb and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdx b/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdx deleted file mode 100644 index 6562832..0000000 Binary files a/README_cache/gfm/unnamed-chunk-7_482ac7c83370220ab9608c6870f2083e.rdx and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.RData b/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.RData deleted file mode 100644 index f7d0eec..0000000 Binary files a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.RData and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdx b/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdx deleted file mode 100644 index 75d82f7..0000000 Binary files a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdx and /dev/null differ diff --git a/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.RData b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.RData new file mode 100644 index 0000000..6f38085 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.RData differ diff --git a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdb b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdb similarity index 55% rename from README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdb rename to README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdb index 5f1064e..a999214 100644 Binary files a/README_cache/gfm/unnamed-chunk-8_661915be3d155615d33e8d437bf2a797.rdb and b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdb differ diff --git a/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdx b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdx new file mode 100644 index 0000000..deee5c6 Binary files /dev/null and b/README_cache/gfm/unnamed-chunk-8_f68e98bbac13a1932bc9db93b38f3a59.rdx differ diff --git a/README_files/figure-gfm/unnamed-chunk-10-1.png b/README_files/figure-gfm/unnamed-chunk-10-1.png index c6562a6..893bd88 100644 Binary files a/README_files/figure-gfm/unnamed-chunk-10-1.png and b/README_files/figure-gfm/unnamed-chunk-10-1.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-10-2.png b/README_files/figure-gfm/unnamed-chunk-10-2.png new file mode 100644 index 0000000..3f85316 Binary files /dev/null and b/README_files/figure-gfm/unnamed-chunk-10-2.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-12-1.png b/README_files/figure-gfm/unnamed-chunk-12-1.png new file mode 100644 index 0000000..abadd4b Binary files /dev/null and b/README_files/figure-gfm/unnamed-chunk-12-1.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-3-1.png b/README_files/figure-gfm/unnamed-chunk-3-1.png index d8f49ce..eb44350 100644 Binary files a/README_files/figure-gfm/unnamed-chunk-3-1.png and b/README_files/figure-gfm/unnamed-chunk-3-1.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-5-1.png b/README_files/figure-gfm/unnamed-chunk-5-1.png index 9a7303f..379ac77 100644 Binary files a/README_files/figure-gfm/unnamed-chunk-5-1.png and b/README_files/figure-gfm/unnamed-chunk-5-1.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-6-1.png b/README_files/figure-gfm/unnamed-chunk-6-1.png index 14e572b..3de4cef 100644 Binary files a/README_files/figure-gfm/unnamed-chunk-6-1.png and b/README_files/figure-gfm/unnamed-chunk-6-1.png differ diff --git a/README_files/figure-gfm/unnamed-chunk-7-1.png b/README_files/figure-gfm/unnamed-chunk-7-1.png index 0628694..1399459 100644 Binary files a/README_files/figure-gfm/unnamed-chunk-7-1.png and b/README_files/figure-gfm/unnamed-chunk-7-1.png differ