├── .gitignore ├── man ├── figures │ ├── logo.png │ ├── README-unnamed-chunk-3-1.png │ ├── README-unnamed-chunk-6-1.png │ └── README-unnamed-chunk-8-1.png ├── ggpte.Rd ├── print.pte_results.Rd ├── print.group_time_att.Rd ├── process_att_gt.Rd ├── summary.pte_results.Rd ├── summary.group_time_att.Rd ├── print.summary.pte_results.Rd ├── pte_results.Rd ├── mboot2.Rd ├── summary.pte_emp_boot.Rd ├── gt_data_frame.Rd ├── attgt_pte_aggregations.Rd ├── attgt_noif.Rd ├── pte_aggte.Rd ├── attgt_if.Rd ├── keep_all_pretreatment_subset.Rd ├── qtt_pte_aggregations.Rd ├── qott_pte_aggregations.Rd ├── keep_all_untreated_subset.Rd ├── did_attgt.Rd ├── group_time_att.Rd ├── pte_emp_boot.Rd ├── two_by_two_subset.Rd ├── pte_attgt.Rd ├── setup_pte_basic.Rd ├── compute.pte.Rd ├── setup_pte.Rd ├── compute.pte2.Rd ├── pte_params.Rd ├── pte_default.Rd └── panel_empirical_bootstrap.Rd ├── tests ├── testthat │ ├── testthat-problems.rds │ ├── test-did-inference.R │ └── test-did.R └── testthat.R ├── docs ├── pkgdown.yml ├── reference │ ├── figures │ │ ├── README-unnamed-chunk-3-1.png │ │ ├── README-unnamed-chunk-6-1.png │ │ └── README-unnamed-chunk-8-1.png │ ├── ggpte.html │ ├── process_att_gt.html │ ├── print.pte_results.html │ ├── summary.pte_results.html │ ├── print.group_time_att.html │ ├── pte_results.html │ ├── mboot2.html │ ├── summary.group_time_att.html │ ├── print.summary.pte_results.html │ ├── summary.pte_emp_boot.html │ ├── qtt_pte_aggregations.html │ ├── qott_pte_aggregations.html │ ├── gt_data_frame.html │ ├── orig2t.html │ ├── t2orig.html │ ├── attgt_noif.html │ ├── attgt_pte_aggregations.html │ ├── attgt_if.html │ └── two_by_two_subset.html ├── link.svg ├── bootstrap-toc.css ├── docsearch.js ├── sitemap.xml ├── pkgdown.js ├── 404.html ├── bootstrap-toc.js └── authors.html ├── .Rbuildignore ├── R ├── startup.R ├── zzz.R ├── imports.R ├── imputation_functions.R ├── ggpte.R ├── pte_aggte.R ├── process_att_gt.R └── subset_functions.R ├── pte.Rproj ├── NAMESPACE ├── DESCRIPTION └── .github └── workflows └── update-citation-cff.yaml /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/man/figures/logo.png -------------------------------------------------------------------------------- /tests/testthat/testthat-problems.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/tests/testthat/testthat-problems.rds -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 2.9.2.1 2 | pkgdown: 2.0.6 3 | pkgdown_sha: ~ 4 | articles: {} 5 | last_built: 2023-05-26T02:34Z 6 | 7 | -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/man/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/man/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-8-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/man/figures/README-unnamed-chunk-8-1.png -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^README\.Rmd$ 2 | ^CITATION\.cff$ 3 | ^\.github$ 4 | ^.*\.Rproj$ 5 | ^\.Rproj\.user$ 6 | ^docs$ 7 | ^R/imputation_functions.R$ 8 | -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-3-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/docs/reference/figures/README-unnamed-chunk-3-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-6-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/docs/reference/figures/README-unnamed-chunk-6-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-8-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bcallaway11/pte/HEAD/docs/reference/figures/README-unnamed-chunk-8-1.png -------------------------------------------------------------------------------- /R/startup.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(libname, pkgname) { 2 | packageStartupMessage("NOTE: The 'pte' package has been renamed to 'ptetools'. Please update your usage.") 3 | } 4 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | utils::globalVariables(c("e", "post", "ciu", "cil", "G", "Y", "att", "id", "name", "period", "att.e", "att.g", "group", "length.e", "length.group", "time.period", ".treat")) 2 | -------------------------------------------------------------------------------- /man/ggpte.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggpte.R 3 | \name{ggpte} 4 | \alias{ggpte} 5 | \title{ggpte} 6 | \usage{ 7 | ggpte(pte_results) 8 | } 9 | \arguments{ 10 | \item{pte_results}{A \code{pte_results} object} 11 | } 12 | \description{ 13 | Simple event study plots for panel treatment effects 14 | } 15 | -------------------------------------------------------------------------------- /R/imports.R: -------------------------------------------------------------------------------- 1 | #' Panel Treatment Effects 2 | #' 3 | #' Tools for estimating treatment effects with panel data. 4 | #' 5 | #' @docType package 6 | #' @name pte 7 | #' @import stats 8 | #' @import utils 9 | #' @import ggplot2 10 | #' @import tidyr 11 | #' @import BMisc 12 | #' @importFrom dplyr bind_rows group_by group_map inner_join mutate transmute 13 | "_PACKAGE" 14 | -------------------------------------------------------------------------------- /pte.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 13 | LaTeX: pdfLaTeX 14 | 15 | BuildType: Package 16 | PackageUseDevtools: Yes 17 | PackageInstallArgs: --no-multiarch --with-keep.source 18 | -------------------------------------------------------------------------------- /man/print.pte_results.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{print.pte_results} 4 | \alias{print.pte_results} 5 | \title{print.pte_results} 6 | \usage{ 7 | \method{print}{pte_results}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a \code{pte_results} object} 11 | 12 | \item{...}{extra arguments} 13 | } 14 | \description{ 15 | prints value of a \code{pte_results} object 16 | } 17 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/testing-design.html#sec-tests-files-overview 7 | # * https://testthat.r-lib.org/articles/special-files.html 8 | 9 | library(testthat) 10 | library(pte) 11 | 12 | test_check("pte") 13 | -------------------------------------------------------------------------------- /man/print.group_time_att.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{print.group_time_att} 4 | \alias{print.group_time_att} 5 | \title{print.group_time_att} 6 | \usage{ 7 | \method{print}{group_time_att}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a \code{group_time_att} object} 11 | 12 | \item{...}{extra arguments} 13 | } 14 | \description{ 15 | prints value of a \code{group_time_att} object 16 | } 17 | -------------------------------------------------------------------------------- /man/process_att_gt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/process_att_gt.R 3 | \name{process_att_gt} 4 | \alias{process_att_gt} 5 | \title{process_att_gt} 6 | \usage{ 7 | process_att_gt(att_gt_results, ptep) 8 | } 9 | \arguments{ 10 | \item{att_gt_results}{ATT(g,t)'s} 11 | 12 | \item{ptep}{\code{pte_params} object} 13 | } 14 | \description{ 15 | process attgt results when influence function is available 16 | } 17 | -------------------------------------------------------------------------------- /man/summary.pte_results.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{summary.pte_results} 4 | \alias{summary.pte_results} 5 | \title{summary.pte_results} 6 | \usage{ 7 | \method{summary}{pte_results}(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{an \code{pte_results} object} 11 | 12 | \item{...}{other arguments} 13 | } 14 | \description{ 15 | A function to summarize \code{pte} results. 16 | } 17 | -------------------------------------------------------------------------------- /man/summary.group_time_att.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{summary.group_time_att} 4 | \alias{summary.group_time_att} 5 | \title{summary.group_time_att} 6 | \usage{ 7 | \method{summary}{group_time_att}(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{an \code{group_time_att} object} 11 | 12 | \item{...}{extra arguments} 13 | } 14 | \description{ 15 | prints a summary of a \code{group_time_att} object 16 | } 17 | -------------------------------------------------------------------------------- /man/print.summary.pte_results.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{print.summary.pte_results} 4 | \alias{print.summary.pte_results} 5 | \title{print.summary.pte_results} 6 | \usage{ 7 | \method{print}{summary.pte_results}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{a \code{summary.pte_results} object} 11 | 12 | \item{...}{extra arguments} 13 | } 14 | \description{ 15 | prints value of a \code{summary.pte_results} object 16 | } 17 | -------------------------------------------------------------------------------- /man/pte_results.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{pte_results} 4 | \alias{pte_results} 5 | \title{pte_results} 6 | \usage{ 7 | pte_results(att_gt, overall_att, event_study, ptep) 8 | } 9 | \arguments{ 10 | \item{att_gt}{attgt results} 11 | 12 | \item{overall_att}{overall_att results} 13 | 14 | \item{event_study}{event_study results} 15 | 16 | \item{ptep}{\code{pte_params} object} 17 | } 18 | \description{ 19 | class for holding pte results 20 | } 21 | -------------------------------------------------------------------------------- /man/mboot2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/process_att_gt.R 3 | \name{mboot2} 4 | \alias{mboot2} 5 | \title{mboot2} 6 | \usage{ 7 | mboot2(inffunc, biters = 1000, alp = 0.05) 8 | } 9 | \arguments{ 10 | \item{inffunc}{influence function matrix} 11 | 12 | \item{biters}{number of bootstrap iterations; default is 100} 13 | 14 | \item{alp}{significance level; default is 0.05} 15 | } 16 | \description{ 17 | function for using multiplier bootstrap to conduct 18 | inference 19 | } 20 | -------------------------------------------------------------------------------- /man/summary.pte_emp_boot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{summary.pte_emp_boot} 4 | \alias{summary.pte_emp_boot} 5 | \title{summary.pte_emp_boot} 6 | \usage{ 7 | \method{summary}{pte_emp_boot}(object, ...) 8 | } 9 | \arguments{ 10 | \item{object}{a \code{pte_emp_boot} object} 11 | 12 | \item{...}{additional function arguments} 13 | } 14 | \value{ 15 | \code{summary.pte_results} object 16 | } 17 | \description{ 18 | Summary for \code{pte_emp_boot} object 19 | } 20 | -------------------------------------------------------------------------------- /R/imputation_functions.R: -------------------------------------------------------------------------------- 1 | # in progress...not sure if we'll actually use this 2 | #' @keywords internal 3 | twfe_imputation <- function(data, ptep) { 4 | 5 | browser() 6 | yname <- ptep$yname 7 | idname <- ptep$idname 8 | tname <- ptep$tname 9 | gname <- ptep$gname 10 | 11 | formla <- paste0(yname, "~", 0) 12 | formla <- paste0(formla, " | ", idname, " + ", tname) 13 | formla <- as.formula(formla) 14 | 15 | pre_data <- data[ ( data[,tname] < data[,gname] ) | data[,gname]==0, ] 16 | 17 | twfe_est <- fixest::feols(formla, data=pre_data) 18 | 19 | y0 <- predict(twfe_est, newdata=data) 20 | 21 | y0 22 | } 23 | -------------------------------------------------------------------------------- /man/gt_data_frame.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{gt_data_frame} 4 | \alias{gt_data_frame} 5 | \title{gt_data_frame} 6 | \usage{ 7 | gt_data_frame(data) 8 | } 9 | \arguments{ 10 | \item{data}{data that will be checked to see if has right format for 11 | computing group-time average treatment effects} 12 | } 13 | \value{ 14 | \code{gt_data_frame} object 15 | } 16 | \description{ 17 | function to take in a data.frame, check if it has the right 18 | columns to be used to calculate a group-time average treatment effect, 19 | and sets the class of the data.frame to include \code{gt_data_frame} 20 | } 21 | -------------------------------------------------------------------------------- /R/ggpte.R: -------------------------------------------------------------------------------- 1 | #' @title ggpte 2 | #' 3 | #' @description Simple event study plots for panel treatment effects 4 | #' 5 | #' @param pte_results A \code{pte_results} object 6 | #' 7 | #' @export 8 | ggpte <- function(pte_results) { 9 | plot_df <- summary(pte_results)$event_study 10 | colnames(plot_df) <- c("e", "att", "se", "cil", "ciu") 11 | plot_df$post <- as.factor(1*(plot_df$e >= 0)) 12 | ggplot(plot_df, aes(x=e, y=att)) + 13 | geom_line(aes(color=post)) + 14 | geom_point(aes(color=post)) + 15 | geom_line(aes(y=ciu), linetype="dashed", alpha=0.5) + 16 | geom_line(aes(y=cil), linetype="dashed", alpha=0.5) + 17 | theme_bw() + 18 | theme(legend.position="bottom") 19 | } 20 | -------------------------------------------------------------------------------- /man/attgt_pte_aggregations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/empirical_bootstrap.R 3 | \name{attgt_pte_aggregations} 4 | \alias{attgt_pte_aggregations} 5 | \title{attgt_pte_aggregations} 6 | \usage{ 7 | attgt_pte_aggregations(attgt.list, ptep) 8 | } 9 | \arguments{ 10 | \item{attgt.list}{list of attgt results from \code{compute.pte}} 11 | 12 | \item{ptep}{\code{pte_params} object} 13 | } 14 | \value{ 15 | \code{pte_emp_boot} object 16 | } 17 | \description{ 18 | Aggregate group-time average treatment effects into 19 | overall, group, and dynamic effects. This function is only used 20 | for (i) computing standard errors using the empirical bootstrap, 21 | and (ii) combining distributions at the (g,t) level 22 | } 23 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /man/attgt_noif.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{attgt_noif} 4 | \alias{attgt_noif} 5 | \title{attgt_noif} 6 | \usage{ 7 | attgt_noif(attgt, extra_gt_returns = NULL) 8 | } 9 | \arguments{ 10 | \item{attgt}{group-time average treatment effect} 11 | 12 | \item{extra_gt_returns}{A place to return anything extra from particular 13 | group-time average treatment effect calculations. For DID, this might 14 | be something like propensity score estimates, regressions of untreated 15 | potential outcomes on covariates. For ife, this could be something 16 | like the first step regression 2sls estimates. This argument is also 17 | potentially useful for debugging.} 18 | } 19 | \value{ 20 | attgt_noif object 21 | } 22 | \description{ 23 | Class for holding group-time average treatment effects 24 | which don't include influence functions 25 | } 26 | -------------------------------------------------------------------------------- /man/pte_aggte.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte_aggte.R 3 | \name{pte_aggte} 4 | \alias{pte_aggte} 5 | \title{pte_aggte} 6 | \usage{ 7 | pte_aggte(attgt, type = "overall") 8 | } 9 | \arguments{ 10 | \item{attgt}{A group_time_att object to be aggregated} 11 | 12 | \item{type}{The type of aggregation to be done. Default is "overall"} 13 | } 14 | \description{ 15 | This is a slight edit of the aggte function from the \code{did} package. 16 | Currently, it only provides aggregations for "overall" treatment effects 17 | and event studies. It also will provide the weights directly which is 18 | currently used for constructing aggregations based on distributions. 19 | The other difference is that, \code{pte_aggte} provides inference results 20 | where the only randomness is coming from the outcomes (not from the group 21 | assignment nor from the covariates). 22 | } 23 | -------------------------------------------------------------------------------- /man/attgt_if.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{attgt_if} 4 | \alias{attgt_if} 5 | \title{attgt_if} 6 | \usage{ 7 | attgt_if(attgt, inf_func, extra_gt_returns = NULL) 8 | } 9 | \arguments{ 10 | \item{attgt}{group-time average treatment effect} 11 | 12 | \item{inf_func}{influence function} 13 | 14 | \item{extra_gt_returns}{A place to return anything extra from particular 15 | group-time average treatment effect calculations. For DID, this might 16 | be something like propensity score estimates, regressions of untreated 17 | potential outcomes on covariates. For ife, this could be something 18 | like the first step regression 2sls estimates. This argument is also 19 | potentially useful for debugging.} 20 | } 21 | \value{ 22 | attgt_if object 23 | } 24 | \description{ 25 | Class for holding group-time average treatment effects 26 | along with their influence function 27 | } 28 | -------------------------------------------------------------------------------- /R/pte_aggte.R: -------------------------------------------------------------------------------- 1 | #' @title pte_aggte 2 | #' 3 | #' @description This is a slight edit of the aggte function from the `did` package. 4 | #' Currently, it only provides aggregations for "overall" treatment effects 5 | #' and event studies. It also will provide the weights directly which is 6 | #' currently used for constructing aggregations based on distributions. 7 | #' The other difference is that, `pte_aggte` provides inference results 8 | #' where the only randomness is coming from the outcomes (not from the group 9 | #' assignment nor from the covariates). 10 | #' 11 | #' @param attgt A group_time_att object to be aggregated 12 | #' @param type The type of aggregation to be done. Default is "overall" 13 | pte_aggte <- function(attgt, 14 | type="overall") { 15 | 16 | group <- attgt$group 17 | time.period <- attgt$time.period 18 | att <- attgt$att 19 | ptep <- attgt$ptep 20 | bstrap <- ptep$bstrap 21 | cband <- ptep$bstrap 22 | alp <- ptep$alp 23 | 24 | 25 | } 26 | -------------------------------------------------------------------------------- /man/keep_all_pretreatment_subset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/subset_functions.R 3 | \name{keep_all_pretreatment_subset} 4 | \alias{keep_all_pretreatment_subset} 5 | \title{keep_all_pretreatment_subset} 6 | \usage{ 7 | keep_all_pretreatment_subset(data, g, tp, ...) 8 | } 9 | \arguments{ 10 | \item{data}{the full dataset} 11 | 12 | \item{g}{the current group} 13 | 14 | \item{tp}{the current time period} 15 | 16 | \item{...}{additional arguments} 17 | } 18 | \value{ 19 | all data but in correct format for computing ATT(g,t) 20 | } 21 | \description{ 22 | A function that takes an original data set and keeps all 23 | data for all groups that are not-yet-treated by period \code{tp} as well 24 | as for group \code{g}. 25 | 26 | In particular, this keeps more data than functions like \code{two_by_two} 27 | subset that use a fixed base period. 28 | 29 | A main use case for this function is the interactive fixed effects approach 30 | proposed in Callaway and Tsyawo (2023). 31 | } 32 | -------------------------------------------------------------------------------- /man/qtt_pte_aggregations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/empirical_bootstrap.R 3 | \name{qtt_pte_aggregations} 4 | \alias{qtt_pte_aggregations} 5 | \title{qtt_pte_aggregations} 6 | \usage{ 7 | qtt_pte_aggregations(attgt.list, ptep, extra_gt_returns) 8 | } 9 | \arguments{ 10 | \item{attgt.list}{list of attgt results from \code{compute.pte}} 11 | 12 | \item{ptep}{\code{pte_params} object} 13 | 14 | \item{extra_gt_returns}{A place to return anything extra from particular 15 | group-time average treatment effect calculations. For DID, this might 16 | be something like propensity score estimates, regressions of untreated 17 | potential outcomes on covariates. For ife, this could be something 18 | like the first step regression 2sls estimates. This argument is also 19 | potentially useful for debugging.} 20 | } 21 | \value{ 22 | \code{pte_emp_boot} object 23 | } 24 | \description{ 25 | Aggregate group-time distributions into qtt versions of 26 | overall, group, and dynamic effects. 27 | } 28 | -------------------------------------------------------------------------------- /man/qott_pte_aggregations.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/empirical_bootstrap.R 3 | \name{qott_pte_aggregations} 4 | \alias{qott_pte_aggregations} 5 | \title{qott_pte_aggregations} 6 | \usage{ 7 | qott_pte_aggregations(attgt.list, ptep, extra_gt_returns) 8 | } 9 | \arguments{ 10 | \item{attgt.list}{list of attgt results from \code{compute.pte}} 11 | 12 | \item{ptep}{\code{pte_params} object} 13 | 14 | \item{extra_gt_returns}{A place to return anything extra from particular 15 | group-time average treatment effect calculations. For DID, this might 16 | be something like propensity score estimates, regressions of untreated 17 | potential outcomes on covariates. For ife, this could be something 18 | like the first step regression 2sls estimates. This argument is also 19 | potentially useful for debugging.} 20 | } 21 | \value{ 22 | \code{pte_emp_boot} object 23 | } 24 | \description{ 25 | Aggregate group-time distribution of the treatment effect into 26 | overall, group, and dynamic effects. 27 | } 28 | -------------------------------------------------------------------------------- /man/keep_all_untreated_subset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/subset_functions.R 3 | \name{keep_all_untreated_subset} 4 | \alias{keep_all_untreated_subset} 5 | \title{keep_all_untreated_subset} 6 | \usage{ 7 | keep_all_untreated_subset(data, g, tp, ...) 8 | } 9 | \arguments{ 10 | \item{data}{the full dataset} 11 | 12 | \item{g}{the current group} 13 | 14 | \item{tp}{the current time period} 15 | 16 | \item{...}{extra arguments to get the subset correct} 17 | } 18 | \value{ 19 | all data but in correct format for computing ATT(g,t) 20 | } 21 | \description{ 22 | A function that takes an original data set and keeps all 23 | pre-treatment data for all groups. For group g, it also includes data 24 | for the current period. 25 | 26 | Also, note that if \code{tp} is still a pre-treatment period for group g, 27 | then periods after \code{tp} will also be dropped for group g. This is a 28 | design choice and is useful especially for estimating placebo 29 | group-time average treatment effects in pre-treatment periods. 30 | 31 | A main use case for this function is to compute ATT(g,t)'s using a global 32 | estimation strategy such as imputation in Gardner (2022). 33 | } 34 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,group_time_att) 4 | S3method(print,pte_results) 5 | S3method(print,summary.pte_results) 6 | S3method(summary,group_time_att) 7 | S3method(summary,pte_emp_boot) 8 | S3method(summary,pte_results) 9 | export(attgt_if) 10 | export(attgt_noif) 11 | export(attgt_pte_aggregations) 12 | export(compute.pte) 13 | export(compute.pte2) 14 | export(did_attgt) 15 | export(ggpte) 16 | export(group_time_att) 17 | export(gt_data_frame) 18 | export(keep_all_pretreatment_subset) 19 | export(keep_all_untreated_subset) 20 | export(mboot2) 21 | export(panel_empirical_bootstrap) 22 | export(process_att_gt) 23 | export(pte) 24 | export(pte2) 25 | export(pte_attgt) 26 | export(pte_default) 27 | export(pte_emp_boot) 28 | export(pte_params) 29 | export(pte_results) 30 | export(qott_pte_aggregations) 31 | export(qtt_pte_aggregations) 32 | export(setup_pte) 33 | export(setup_pte_basic) 34 | export(two_by_two_subset) 35 | import(BMisc) 36 | import(ggplot2) 37 | import(stats) 38 | import(tidyr) 39 | import(utils) 40 | importFrom(dplyr,bind_rows) 41 | importFrom(dplyr,group_by) 42 | importFrom(dplyr,group_map) 43 | importFrom(dplyr,inner_join) 44 | importFrom(dplyr,mutate) 45 | importFrom(dplyr,transmute) 46 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: pte 2 | Title: Panel Treatment Effects 3 | Version: 0.0.0.9000 4 | Authors@R: 5 | person(given = "Brantly", 6 | family = "Callaway", 7 | role = c("aut", "cre"), 8 | email = "brantly.callaway@uga.edu") 9 | URL: https://github.com/bcallaway11/pte 10 | Description: This is fairly generic code for estimating treatment effects with panel data. This is useful code in my own work and will perhaps be useful to others. It builds heavily on the \code{did} package. In particular, it breaks into separate steps organizing the data, looping over groups and time periods, computing group-time average treatment effects, and aggregating group-time average treatment effects. Often, one is able to implement a new identification/estimation procedure by simply replacing the step on estimating group-time average treatment effects. See several different examples of this approach in the README. 11 | License: GPL-3 12 | Encoding: UTF-8 13 | LazyData: true 14 | Roxygen: list(markdown = TRUE) 15 | RoxygenNote: 7.3.2 16 | Imports: 17 | BMisc (>= 1.4.7), 18 | Matrix, 19 | did (>= 2.0.0), 20 | ggplot2, 21 | DRDID, 22 | tidyr, 23 | dplyr, 24 | pbapply 25 | Suggests: 26 | testthat (>= 3.0.0) 27 | Config/testthat/edition: 3 28 | -------------------------------------------------------------------------------- /man/did_attgt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/attgt_functions.R 3 | \name{did_attgt} 4 | \alias{did_attgt} 5 | \title{did_attgt} 6 | \usage{ 7 | did_attgt(gt_data, xformla, ...) 8 | } 9 | \arguments{ 10 | \item{gt_data}{data that is "local" to a particular group-time average 11 | treatment effect} 12 | 13 | \item{xformla}{one-sided formula for covariates used in the propensity score 14 | and outcome regression models} 15 | 16 | \item{...}{extra function arguments; not used here} 17 | } 18 | \value{ 19 | attgt_if 20 | } 21 | \description{ 22 | Takes a "local" data.frame and computes 23 | an estimate of a group time average treatment effect 24 | and a corresponding influence function using a difference in differences 25 | approach. 26 | 27 | The code relies on \code{gt_data} having certain variables defined. 28 | In particular, there should be an \code{id} column (individual identifier), 29 | \code{D} (treated group identifier), \code{period} (time period), \code{name} 30 | (equal to "pre" for pre-treatment periods and equal to "post" for post 31 | treatment periods), \code{Y} (outcome). 32 | 33 | In our case, we call \code{pte::two_by_two_subset} which sets up the 34 | data to have this format before the call to \code{did_attgt}. 35 | } 36 | -------------------------------------------------------------------------------- /tests/testthat/test-did-inference.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | # inference tests for did 3 | #------------------------------------------------------------------------ 4 | 5 | library(did) 6 | library(pbapply) 7 | 8 | 9 | # skip_inf <- menu(c("run", "skip"), title="would you like to run or skip the inference tests?") 10 | # skip_inf <- skip_inf == 2 11 | 12 | test_that("tests for inference", { 13 | # skip_if(skip_inf) 14 | # cl <- as.numeric(readline("how many clusters would like to use for the inference tests? ")) 15 | cl <- 1 16 | mc_sims <- 100 17 | rejs <- pblapply(1:mc_sims, function(mc) { 18 | sp <- did::reset.sim() 19 | data <- did::build_sim_dataset(sp) 20 | 21 | res <- pte( 22 | yname = "Y", 23 | gname = "G", 24 | tname = "period", 25 | idname = "id", 26 | data = data, 27 | setup_pte_fun = setup_pte, 28 | subset_fun = two_by_two_subset, 29 | attgt_fun = did_attgt, 30 | xformla = ~X 31 | ) 32 | # truth is that att = 1 33 | tstat <- (res$overall_att$overall.att - 1) / res$overall_att$overall.se 34 | rej <- 1 * (abs(tstat) > qnorm(.975)) 35 | rej 36 | }, cl = cl) 37 | 38 | rej_frac <- mean(unlist(rejs)) 39 | 40 | expect_equal(rej_frac, 0.06, tolerance = .05) # make test fail if reject 0 41 | }) 42 | -------------------------------------------------------------------------------- /man/group_time_att.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{group_time_att} 4 | \alias{group_time_att} 5 | \title{group_time_att} 6 | \usage{ 7 | group_time_att( 8 | group, 9 | time.period, 10 | att, 11 | V_analytical, 12 | se, 13 | crit_val, 14 | inf_func, 15 | n, 16 | W, 17 | Wpval, 18 | cband, 19 | alp, 20 | ptep, 21 | extra_gt_returns 22 | ) 23 | } 24 | \arguments{ 25 | \item{group}{numeric vector of groups for ATT(g,t)} 26 | 27 | \item{time.period}{numeric vector of time periods for ATT(g,t)} 28 | 29 | \item{att}{numeric vector containing the value of ATT(g,t) for 30 | corresponding group and time period} 31 | 32 | \item{V_analytical}{analytical asymptotic variance matrix for ATT(g,t)'s} 33 | 34 | \item{se}{numeric vector of standard errors} 35 | 36 | \item{crit_val}{critical value (usually a critical value for conducting 37 | uniform inference)} 38 | 39 | \item{inf_func}{matrix of influence function} 40 | 41 | \item{n}{number of unique individuals} 42 | 43 | \item{W}{Wald statistic for ATT(g,t) version of pre-test of parallel trends 44 | assumption} 45 | 46 | \item{Wpval}{p-value for Wald pre-test of ATT(g,t) version of parallel 47 | trends assumption} 48 | 49 | \item{cband}{logical indicating whether or not to report a confidence band} 50 | 51 | \item{alp}{significance level} 52 | 53 | \item{ptep}{\code{pte_params} object} 54 | 55 | \item{extra_gt_returns}{list containing extra returns at the group-time level} 56 | } 57 | \value{ 58 | object of class \code{group_time_att} 59 | } 60 | \description{ 61 | group_time_att class 62 | } 63 | -------------------------------------------------------------------------------- /man/pte_emp_boot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/classes.R 3 | \name{pte_emp_boot} 4 | \alias{pte_emp_boot} 5 | \title{pte_emp_boot} 6 | \usage{ 7 | pte_emp_boot( 8 | attgt_results, 9 | overall_results, 10 | group_results, 11 | dyn_results, 12 | overall_weights = NULL, 13 | dyn_weights = NULL, 14 | group_weights = NULL, 15 | extra_gt_returns = NULL 16 | ) 17 | } 18 | \arguments{ 19 | \item{attgt_results}{\code{data.frame} holding attgt results} 20 | 21 | \item{overall_results}{\code{data.frame} holding overall results} 22 | 23 | \item{group_results}{\code{data.frame} holding group results} 24 | 25 | \item{dyn_results}{\code{data.frame} holding dynamic results} 26 | 27 | \item{overall_weights}{vector containing weights on underlying ATT(g,t) 28 | for overall treatment effect parameter} 29 | 30 | \item{dyn_weights}{list containing weights on underlying ATT(g,t) 31 | for each value of \code{e} corresponding to the dynamic treatment 32 | effect parameters.} 33 | 34 | \item{group_weights}{list containing weights on underlying ATT(g,t) 35 | corresponding to deliver averaged group-specific treatment effects} 36 | 37 | \item{extra_gt_returns}{A place to return anything extra from particular 38 | group-time average treatment effect calculations. For DID, this might 39 | be something like propensity score estimates, regressions of untreated 40 | potential outcomes on covariates. For ife, this could be something 41 | like the first step regression 2sls estimates. This argument is also 42 | potentially useful for debugging.} 43 | } 44 | \value{ 45 | pte_emp_boot object 46 | } 47 | \description{ 48 | pte_emp_boot 49 | 50 | Class for holding \code{pte} empirical bootstrap results 51 | } 52 | -------------------------------------------------------------------------------- /.github/workflows/update-citation-cff.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/master/examples 2 | # The action runs when: 3 | # - A new release is published 4 | # - The DESCRIPTION or inst/CITATION are modified 5 | # - Can be run manually 6 | # For customizing the triggers, visit https://docs.github.com/en/actions/learn-github-actions/events-that-trigger-workflows 7 | on: 8 | release: 9 | types: [published] 10 | push: 11 | branches: [master, main] 12 | paths: 13 | - DESCRIPTION 14 | - inst/CITATION 15 | workflow_dispatch: 16 | 17 | name: Update CITATION.cff 18 | 19 | jobs: 20 | update-citation-cff: 21 | runs-on: macos-latest 22 | env: 23 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 24 | steps: 25 | - uses: actions/checkout@v2 26 | - uses: r-lib/actions/setup-r@v2 27 | - uses: r-lib/actions/setup-r-dependencies@v2 28 | with: 29 | extra-packages: | 30 | any::cffr 31 | any::V8 32 | 33 | - name: Update CITATION.cff 34 | run: | 35 | 36 | library(cffr) 37 | 38 | # Customize with your own code 39 | # See https://docs.ropensci.org/cffr/articles/cffr.html 40 | 41 | # Write your own keys 42 | mykeys <- list() 43 | 44 | # Create your CITATION.cff file 45 | cff_write(keys = mykeys) 46 | 47 | shell: Rscript {0} 48 | 49 | - name: Commit results 50 | run: | 51 | git config --local user.name "$GITHUB_ACTOR" 52 | git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com" 53 | git add CITATION.cff 54 | git commit -m 'Update CITATION.cff' || echo "No changes to commit" 55 | git push origin || echo "No changes to commit" 56 | -------------------------------------------------------------------------------- /man/two_by_two_subset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/subset_functions.R 3 | \name{two_by_two_subset} 4 | \alias{two_by_two_subset} 5 | \title{two_by_two_subset} 6 | \usage{ 7 | two_by_two_subset( 8 | data, 9 | g, 10 | tp, 11 | control_group = "notyettreated", 12 | anticipation = 0, 13 | base_period = "varying", 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{data}{the full dataset} 19 | 20 | \item{g}{the current group} 21 | 22 | \item{tp}{the current time period} 23 | 24 | \item{control_group}{whether to use "notyettreated" (default) or 25 | "nevertreated"} 26 | 27 | \item{anticipation}{the number of periods of anticipation (i.e., number 28 | of periods before the treatment happens where the treatment can "already" 29 | affect the outcome)} 30 | 31 | \item{base_period}{The type of base period to use. This only affects 32 | the numeric value of results in pre-treatment periods. Results in 33 | post-treatment periods are not affected by this choice. The default 34 | is "varying", where the base period will "back up" to the immediately 35 | preceding period in pre-treatment periods. The other option is "universal" 36 | where the base period is fixed in pre-treatment periods to be the period 37 | right before the treatment starts. "Universal" is commonly used in 38 | difference-in-differences applications, but can be unnatural for other 39 | identification strategies.} 40 | 41 | \item{...}{extra arguments to get the subset correct} 42 | } 43 | \value{ 44 | list that contains correct subset of data, \code{n1} 45 | number of observations 46 | in this subset, and \code{disidx} a vector of the correct ids for this 47 | subset. 48 | } 49 | \description{ 50 | A function for computing a 2x2 subset of original data. 51 | This is the subset with post treatment periods separately for the 52 | treated group and comparison group and pre-treatment periods in the period 53 | immediately before the treated group became treated. 54 | } 55 | -------------------------------------------------------------------------------- /man/pte_attgt.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/attgt_functions.R 3 | \name{pte_attgt} 4 | \alias{pte_attgt} 5 | \title{pte_attgt} 6 | \usage{ 7 | pte_attgt( 8 | gt_data, 9 | xformla, 10 | d_outcome = FALSE, 11 | d_covs_formula = ~-1, 12 | lagged_outcome_cov = FALSE, 13 | est_method = "dr", 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{gt_data}{data that is "local" to a particular group-time average 19 | treatment effect} 20 | 21 | \item{xformla}{one-sided formula for covariates used in the propensity score 22 | and outcome regression models} 23 | 24 | \item{d_outcome}{Whether or not to take the first difference of the outcome. 25 | The default is FALSE. To use difference-in-differences, set this to be TRUE.} 26 | 27 | \item{d_covs_formula}{A formula for time varying covariates to enter the 28 | first estimation step models. The default is not to include any, and, hence, 29 | to only include pre-treatment covariats.} 30 | 31 | \item{lagged_outcome_cov}{Whether to include the lagged outcome as a covariate. 32 | Default is FALSE.} 33 | 34 | \item{est_method}{Which type of estimation method to use. Default is "dr" for 35 | doubly robust. The other option is "reg" for regression adjustment.} 36 | 37 | \item{...}{extra function arguments; not used here} 38 | } 39 | \value{ 40 | attgt_if 41 | } 42 | \description{ 43 | \code{pte_attgt} takes a "local" data.frame and computes 44 | an estimate of a group time average treatment effect 45 | and a corresponding influence function. This function generalizes 46 | a number of existing methods. 47 | 48 | The code relies on \code{this.data} having certain variables defined. 49 | In particular, there should be an \code{id} column (individual identifier), 50 | \code{G} (group identifier), \code{period} (time period), \code{name} 51 | (equal to "pre" for pre-treatment periods and equal to "post" for post 52 | treatment periods), \code{Y} (outcome). 53 | 54 | In our case, we call \code{pte::two_by_two_subset} which sets up the 55 | data to have this format before the call to \code{pte_attgt} 56 | } 57 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /man/setup_pte_basic.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte_params.R 3 | \name{setup_pte_basic} 4 | \alias{setup_pte_basic} 5 | \title{Example setup panel treatment effects parameters} 6 | \usage{ 7 | setup_pte_basic( 8 | yname, 9 | gname, 10 | tname, 11 | idname, 12 | data, 13 | cband = TRUE, 14 | alp = 0.05, 15 | boot_type = "multiplier", 16 | gt_type = "att", 17 | ret_quantile = 0.5, 18 | biters = 100, 19 | cl = 1, 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{yname}{Name of outcome in \code{data}} 25 | 26 | \item{gname}{Name of group in \code{data}} 27 | 28 | \item{tname}{Name of time period in \code{data}} 29 | 30 | \item{idname}{Name of id in \code{data}} 31 | 32 | \item{data}{balanced panel data} 33 | 34 | \item{cband}{whether or not to report a uniform (instead of pointwise) 35 | confidence band (default is TRUE)} 36 | 37 | \item{alp}{significance level; default is 0.05} 38 | 39 | \item{boot_type}{which type of bootstrap to use} 40 | 41 | \item{gt_type}{which type of group-time effects are computed. 42 | The default is "att". Different estimation strategies can implement 43 | their own choices for \code{gt_type}} 44 | 45 | \item{ret_quantile}{For functions that compute quantile treatment effects, 46 | this is a specific quantile at which to report results, e.g., 47 | \code{ret_quantile = 0.5} will return that the qte at the median.} 48 | 49 | \item{biters}{number of bootstrap iterations; default is 100} 50 | 51 | \item{cl}{number of clusters to be used when bootstrapping; default is 1} 52 | 53 | \item{...}{additional arguments} 54 | } 55 | \value{ 56 | \code{pte_params} object 57 | } 58 | \description{ 59 | This is a lightweight (example) function for how to setup 60 | the data to be used in the \code{pte} package. 61 | 62 | \code{setup_pte_basic} takes in information about the structure of \code{data} 63 | and returns a \code{pte_params} object. The key piece of information 64 | that is computed by this function is the list of groups and list of 65 | time periods where ATT(g,t) should be computed. In particular, this function 66 | omits the never-treated group but includes all other groups and drops the first 67 | time period. This setup is basically geared towards the 2x2 case --- 68 | i.e., where ATT could be identified with two periods, a treated and 69 | untreated group, and the first period being pre-treatment for both groups. 70 | This is the relevant case for DID, but is also relevant for other cases as well. 71 | However, for example, if more pre-treatment periods were needed, then this 72 | function should be replaced by something else. 73 | 74 | For code that is written with the idea of being easy-to-use by other 75 | researchers, this is a good place to do some error handling / checking 76 | that the data is in the correct format, etc. 77 | } 78 | -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | /404.html 5 | 6 | 7 | /authors.html 8 | 9 | 10 | /index.html 11 | 12 | 13 | /reference/attgt_if.html 14 | 15 | 16 | /reference/attgt_noif.html 17 | 18 | 19 | /reference/attgt_pte_aggregations.html 20 | 21 | 22 | /reference/compute.pte.html 23 | 24 | 25 | /reference/compute.pte2.html 26 | 27 | 28 | /reference/did_attgt.html 29 | 30 | 31 | /reference/ggpte.html 32 | 33 | 34 | /reference/group_time_att.html 35 | 36 | 37 | /reference/gt_data_frame.html 38 | 39 | 40 | /reference/index.html 41 | 42 | 43 | /reference/mboot2.html 44 | 45 | 46 | /reference/orig2t.html 47 | 48 | 49 | /reference/panel_empirical_bootstrap.html 50 | 51 | 52 | /reference/print.group_time_att.html 53 | 54 | 55 | /reference/print.pte_results.html 56 | 57 | 58 | /reference/print.summary.pte_results.html 59 | 60 | 61 | /reference/process_att_gt.html 62 | 63 | 64 | /reference/pte.html 65 | 66 | 67 | /reference/pte2.html 68 | 69 | 70 | /reference/pte_aggte.html 71 | 72 | 73 | /reference/pte_attgt.html 74 | 75 | 76 | /reference/pte_default.html 77 | 78 | 79 | /reference/pte_emp_boot.html 80 | 81 | 82 | /reference/pte_params.html 83 | 84 | 85 | /reference/pte_results.html 86 | 87 | 88 | /reference/qott_pte_aggregations.html 89 | 90 | 91 | /reference/qtt_pte_aggregations.html 92 | 93 | 94 | /reference/setup_pte.html 95 | 96 | 97 | /reference/setup_pte_basic.html 98 | 99 | 100 | /reference/summary.group_time_att.html 101 | 102 | 103 | /reference/summary.pte_emp_boot.html 104 | 105 | 106 | /reference/summary.pte_results.html 107 | 108 | 109 | /reference/t2orig.html 110 | 111 | 112 | /reference/two_by_two_subset.html 113 | 114 | 115 | -------------------------------------------------------------------------------- /man/compute.pte.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte.R 3 | \name{compute.pte} 4 | \alias{compute.pte} 5 | \title{compute.pte} 6 | \usage{ 7 | compute.pte(ptep, subset_fun, attgt_fun, ...) 8 | } 9 | \arguments{ 10 | \item{ptep}{\code{pte_params} object} 11 | 12 | \item{subset_fun}{This is a function that should take in \code{data}, 13 | \code{g} (for group), \code{tp} (for time period), and \code{...} 14 | and be able to return the appropriate \code{data.frame} that can be used 15 | by \code{attgt_fun} to produce ATT(g=g,t=tp). The data frame should 16 | be constructed using \code{gt_data_frame} in order to guarantee that 17 | it has the appropriate columns that identify which group an observation 18 | belongs to, etc.} 19 | 20 | \item{attgt_fun}{This is a function that should work in the case where 21 | there is a single group and the "right" number of time periods to 22 | recover an estimate of the ATT. For example, in the contest of 23 | difference in differences, it would need to work for a single group, 24 | find the appropriate comparison group (untreated units), find the right 25 | time periods (pre- and post-treatment), and then recover an estimate 26 | of ATT for that group. It will be called over and over separately 27 | by groups and by time periods to compute ATT(g,t)'s. 28 | 29 | The function needs to work in a very specific way. It should take in the 30 | arguments: \code{data}, \code{...}. \code{data} should be constructed 31 | using the function \code{gt_data_frame} which checks to make sure 32 | that \code{data} has the correct columns defined. 33 | \code{...} are additional arguments (such as 34 | formulas for covariates) that \code{attgt_fun} needs. From these arguments 35 | \code{attgt_fun} must return a list with element \code{ATT} containing the 36 | group-time average treatment effect for that group and that time period. 37 | 38 | If \code{attgt_fun} returns an influence function (which should be provided 39 | in a list element named \code{inf_func}), then the code will use the 40 | multiplier bootstrap to compute standard errors for group-time average 41 | treatment effects, an overall treatment effect parameter, and a dynamic 42 | treatment effect parameter (i.e., event study parameter). If 43 | \code{attgt_fun} does not return an influence function, then the same 44 | objects will be computed using the empirical bootstrap. This is usually 45 | (perhaps substantially) easier to code, but also will usually be (perhaps 46 | substantially) computationally slower.} 47 | 48 | \item{...}{extra arguments that can be passed to create the correct subsets 49 | of the data (depending on \code{subset_fun}), to estimate group time 50 | average treatment effects (depending on \code{attgt_fun}), or to 51 | aggregating treatment effects (particularly useful are \code{min_e}, 52 | \code{max_e}, and \code{balance_e} arguments to event study aggregations)} 53 | } 54 | \value{ 55 | list of attgt results and, sometimes, and influence function 56 | } 57 | \description{ 58 | Function that actually computes panel treatment effects 59 | } 60 | -------------------------------------------------------------------------------- /man/setup_pte.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte_params.R 3 | \name{setup_pte} 4 | \alias{setup_pte} 5 | \title{Setup panel treatment effects parameters} 6 | \usage{ 7 | setup_pte( 8 | yname, 9 | gname, 10 | tname, 11 | idname, 12 | data, 13 | required_pre_periods = 1, 14 | anticipation = 0, 15 | base_period = "varying", 16 | cband = TRUE, 17 | alp = 0.05, 18 | boot_type = "multiplier", 19 | weightsname = NULL, 20 | gt_type = "att", 21 | ret_quantile = 0.5, 22 | biters = 100, 23 | cl = 1, 24 | ... 25 | ) 26 | } 27 | \arguments{ 28 | \item{yname}{Name of outcome in \code{data}} 29 | 30 | \item{gname}{Name of group in \code{data}} 31 | 32 | \item{tname}{Name of time period in \code{data}} 33 | 34 | \item{idname}{Name of id in \code{data}} 35 | 36 | \item{data}{balanced panel data} 37 | 38 | \item{required_pre_periods}{The number of required pre-treatment periods to implement 39 | the estimation strategy. Default is 1.} 40 | 41 | \item{anticipation}{how many periods before the treatment actually takes 42 | place that it can have an effect on outcomes} 43 | 44 | \item{base_period}{The type of base period to use. This only affects 45 | the numeric value of results in pre-treatment periods. Results in 46 | post-treatment periods are not affected by this choice. The default 47 | is "varying", where the base period will "back up" to the immediately 48 | preceding period in pre-treatment periods. The other option is "universal" 49 | where the base period is fixed in pre-treatment periods to be the period 50 | right before the treatment starts. "Universal" is commonly used in 51 | difference-in-differences applications, but can be unnatural for other 52 | identification strategies.} 53 | 54 | \item{cband}{whether or not to report a uniform (instead of pointwise) 55 | confidence band (default is TRUE)} 56 | 57 | \item{alp}{significance level; default is 0.05} 58 | 59 | \item{boot_type}{which type of bootstrap to use} 60 | 61 | \item{weightsname}{The name of the column that contains sampling weights. 62 | The defaul is NULL, in which case no sampling weights are used.} 63 | 64 | \item{gt_type}{which type of group-time effects are computed. 65 | The default is "att". Different estimation strategies can implement 66 | their own choices for \code{gt_type}} 67 | 68 | \item{ret_quantile}{For functions that compute quantile treatment effects, 69 | this is a specific quantile at which to report results, e.g., 70 | \code{ret_quantile = 0.5} will return that the qte at the median.} 71 | 72 | \item{biters}{number of bootstrap iterations; default is 100} 73 | 74 | \item{cl}{number of clusters to be used when bootstrapping; default is 1} 75 | 76 | \item{...}{additional arguments} 77 | } 78 | \value{ 79 | \code{pte_params} object 80 | } 81 | \description{ 82 | This is a function for how to setup 83 | the data to be used in the \code{pte} package. 84 | 85 | The \code{setup_pte} function builds on \code{setup_pte_basic} and 86 | attempts to provide a general purpose function (with error handling) 87 | to arrange the data in a way that can be processed by \code{subset_fun} 88 | and \code{attgt_fun} in the next steps. 89 | } 90 | -------------------------------------------------------------------------------- /man/compute.pte2.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte.R 3 | \name{compute.pte2} 4 | \alias{compute.pte2} 5 | \title{compute.pte2} 6 | \usage{ 7 | compute.pte2(ptep, subset_fun, attgt_fun, ...) 8 | } 9 | \arguments{ 10 | \item{ptep}{\code{pte_params} object} 11 | 12 | \item{subset_fun}{This is a function that should take in \code{data}, 13 | \code{g} (for group), \code{tp} (for time period), and \code{...} 14 | and be able to return the appropriate \code{data.frame} that can be used 15 | by \code{attgt_fun} to produce ATT(g=g,t=tp). The data frame should 16 | be constructed using \code{gt_data_frame} in order to guarantee that 17 | it has the appropriate columns that identify which group an observation 18 | belongs to, etc.} 19 | 20 | \item{attgt_fun}{This is a function that should work in the case where 21 | there is a single group and the "right" number of time periods to 22 | recover an estimate of the ATT. For example, in the contest of 23 | difference in differences, it would need to work for a single group, 24 | find the appropriate comparison group (untreated units), find the right 25 | time periods (pre- and post-treatment), and then recover an estimate 26 | of ATT for that group. It will be called over and over separately 27 | by groups and by time periods to compute ATT(g,t)'s. 28 | 29 | The function needs to work in a very specific way. It should take in the 30 | arguments: \code{data}, \code{...}. \code{data} should be constructed 31 | using the function \code{gt_data_frame} which checks to make sure 32 | that \code{data} has the correct columns defined. 33 | \code{...} are additional arguments (such as 34 | formulas for covariates) that \code{attgt_fun} needs. From these arguments 35 | \code{attgt_fun} must return a list with element \code{ATT} containing the 36 | group-time average treatment effect for that group and that time period. 37 | 38 | If \code{attgt_fun} returns an influence function (which should be provided 39 | in a list element named \code{inf_func}), then the code will use the 40 | multiplier bootstrap to compute standard errors for group-time average 41 | treatment effects, an overall treatment effect parameter, and a dynamic 42 | treatment effect parameter (i.e., event study parameter). If 43 | \code{attgt_fun} does not return an influence function, then the same 44 | objects will be computed using the empirical bootstrap. This is usually 45 | (perhaps substantially) easier to code, but also will usually be (perhaps 46 | substantially) computationally slower.} 47 | 48 | \item{...}{extra arguments that can be passed to create the correct subsets 49 | of the data (depending on \code{subset_fun}), to estimate group time 50 | average treatment effects (depending on \code{attgt_fun}), or to 51 | aggregating treatment effects (particularly useful are \code{min_e}, 52 | \code{max_e}, and \code{balance_e} arguments to event study aggregations)} 53 | } 54 | \value{ 55 | list of attgt results and, sometimes, an influence function 56 | } 57 | \description{ 58 | Function that actually computes panel treatment effects. 59 | The difference relative to \code{compute.pte} is that this function 60 | loops over time periods first (instead of groups) and tries to 61 | estimate model for untreated potential outcomes jointly for all groups. 62 | } 63 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $("div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /man/pte_params.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte_params.R 3 | \name{pte_params} 4 | \alias{pte_params} 5 | \title{pte_params} 6 | \usage{ 7 | pte_params( 8 | yname, 9 | gname, 10 | tname, 11 | idname, 12 | data, 13 | glist, 14 | tlist, 15 | cband, 16 | alp, 17 | boot_type, 18 | anticipation = NULL, 19 | base_period = NULL, 20 | weightsname = NULL, 21 | control_group = "notyettreated", 22 | gt_type = "att", 23 | ret_quantile = 0.5, 24 | global_fun = FALSE, 25 | time_period_fun = FALSE, 26 | group_fun = FALSE, 27 | biters, 28 | cl 29 | ) 30 | } 31 | \arguments{ 32 | \item{yname}{Name of outcome in \code{data}} 33 | 34 | \item{gname}{Name of group in \code{data}} 35 | 36 | \item{tname}{Name of time period in \code{data}} 37 | 38 | \item{idname}{Name of id in \code{data}} 39 | 40 | \item{data}{balanced panel data} 41 | 42 | \item{glist}{list of groups to create group-time average treatment effects 43 | for} 44 | 45 | \item{tlist}{list of time periods to create group-time average treatment 46 | effects for} 47 | 48 | \item{cband}{whether or not to report a uniform (instead of pointwise) 49 | confidence band (default is TRUE)} 50 | 51 | \item{alp}{significance level; default is 0.05} 52 | 53 | \item{boot_type}{which type of bootstrap to use} 54 | 55 | \item{anticipation}{how many periods before the treatment actually takes 56 | place that it can have an effect on outcomes} 57 | 58 | \item{base_period}{The type of base period to use. This only affects 59 | the numeric value of results in pre-treatment periods. Results in 60 | post-treatment periods are not affected by this choice. The default 61 | is "varying", where the base period will "back up" to the immediately 62 | preceding period in pre-treatment periods. The other option is "universal" 63 | where the base period is fixed in pre-treatment periods to be the period 64 | right before the treatment starts. "Universal" is commonly used in 65 | difference-in-differences applications, but can be unnatural for other 66 | identification strategies.} 67 | 68 | \item{weightsname}{The name of the column that contains sampling weights. 69 | The defaul is NULL, in which case no sampling weights are used.} 70 | 71 | \item{control_group}{Which group is used as the comparison group. 72 | The default choice is "notyettreated", but 73 | different estimation strategies can implement their own choices 74 | for the control group} 75 | 76 | \item{gt_type}{which type of group-time effects are computed. 77 | The default is "att". Different estimation strategies can implement 78 | their own choices for \code{gt_type}} 79 | 80 | \item{ret_quantile}{For functions that compute quantile treatment effects, 81 | this is a specific quantile at which to report results, e.g., 82 | \code{ret_quantile = 0.5} will return that the qte at the median.} 83 | 84 | \item{global_fun}{Logical indicating whether or not untreated potential 85 | outcomes can be estimated in one shot, i.e., for all groups and time periods. 86 | Main use case would be for one-shot imputation estimators. Not supported yet.} 87 | 88 | \item{time_period_fun}{Logical indicating whether or not untreated potential 89 | outcomes can be estimated for all groups in the same time period. Not supported yet.} 90 | 91 | \item{group_fun}{Logical indicating whether or not untreated potential outcomes 92 | can be estimated for all time periods for a single group. Not supported yet. 93 | These functions aim at reducing or eliminating running the same code multiple times.} 94 | 95 | \item{biters}{number of bootstrap iterations; default is 100} 96 | 97 | \item{cl}{number of clusters to be used when bootstrapping; default is 1} 98 | } 99 | \description{ 100 | Objects that contain pte parameters 101 | } 102 | -------------------------------------------------------------------------------- /man/pte_default.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/pte.R 3 | \name{pte_default} 4 | \alias{pte_default} 5 | \title{pte_default} 6 | \usage{ 7 | pte_default( 8 | yname, 9 | gname, 10 | tname, 11 | idname, 12 | data, 13 | xformla = ~1, 14 | d_outcome = FALSE, 15 | d_covs_formula = ~-1, 16 | lagged_outcome_cov = FALSE, 17 | est_method = "dr", 18 | anticipation = 0, 19 | base_period = "varying", 20 | control_group = "notyettreated", 21 | weightsname = NULL, 22 | cband = TRUE, 23 | alp = 0.05, 24 | boot_type = "multiplier", 25 | biters = 100, 26 | cl = 1 27 | ) 28 | } 29 | \arguments{ 30 | \item{yname}{Name of outcome in \code{data}} 31 | 32 | \item{gname}{Name of group in \code{data}} 33 | 34 | \item{tname}{Name of time period in \code{data}} 35 | 36 | \item{idname}{Name of id in \code{data}} 37 | 38 | \item{data}{balanced panel data} 39 | 40 | \item{xformla}{one-sided formula for covariates used in the propensity score 41 | and outcome regression models} 42 | 43 | \item{d_outcome}{Whether or not to take the first difference of the outcome. 44 | The default is FALSE. To use difference-in-differences, set this to be TRUE.} 45 | 46 | \item{d_covs_formula}{A formula for time varying covariates to enter the 47 | first estimation step models. The default is not to include any, and, hence, 48 | to only include pre-treatment covariats.} 49 | 50 | \item{lagged_outcome_cov}{Whether to include the lagged outcome as a covariate. 51 | Default is FALSE.} 52 | 53 | \item{est_method}{Which type of estimation method to use. Default is "dr" for 54 | doubly robust. The other option is "reg" for regression adjustment.} 55 | 56 | \item{anticipation}{how many periods before the treatment actually takes 57 | place that it can have an effect on outcomes} 58 | 59 | \item{base_period}{The type of base period to use. This only affects 60 | the numeric value of results in pre-treatment periods. Results in 61 | post-treatment periods are not affected by this choice. The default 62 | is "varying", where the base period will "back up" to the immediately 63 | preceding period in pre-treatment periods. The other option is "universal" 64 | where the base period is fixed in pre-treatment periods to be the period 65 | right before the treatment starts. "Universal" is commonly used in 66 | difference-in-differences applications, but can be unnatural for other 67 | identification strategies.} 68 | 69 | \item{control_group}{Which group is used as the comparison group. 70 | The default choice is "notyettreated", but 71 | different estimation strategies can implement their own choices 72 | for the control group} 73 | 74 | \item{weightsname}{The name of the column that contains sampling weights. 75 | The defaul is NULL, in which case no sampling weights are used.} 76 | 77 | \item{cband}{whether or not to report a uniform (instead of pointwise) 78 | confidence band (default is TRUE)} 79 | 80 | \item{alp}{significance level; default is 0.05} 81 | 82 | \item{boot_type}{should be one of "multiplier" (the default) or "empirical". 83 | The multiplier bootstrap is generally much faster, but \code{attgt_fun} needs 84 | to provide an expression for the influence function (which could be challenging 85 | to figure out). If no influence function is provided, then the \code{pte} 86 | package will use the empirical bootstrap no matter what the value of this 87 | parameter.} 88 | 89 | \item{biters}{number of bootstrap iterations; default is 100} 90 | 91 | \item{cl}{number of clusters to be used when bootstrapping; default is 1} 92 | } 93 | \value{ 94 | \code{pte_results} object 95 | } 96 | \description{ 97 | This is a generic/example wrapper for a call to the \code{pte} function. 98 | 99 | This function provides access to difference-in-differences and unconfoundedness 100 | based identification/estimation strategies given (i) panel data and (ii) 101 | staggered treatment adoption 102 | } 103 | -------------------------------------------------------------------------------- /tests/testthat/test-did.R: -------------------------------------------------------------------------------- 1 | #------------------------------------------------------------------------ 2 | # Some tests for `did` 3 | #------------------------------------------------------------------------ 4 | 5 | library(did) 6 | 7 | test_that("did basics", { 8 | sp <- did::reset.sim() 9 | data <- did::build_sim_dataset(sp) 10 | 11 | res <- pte(yname="Y", 12 | gname="G", 13 | tname="period", 14 | idname="id", 15 | data=data, 16 | setup_pte_fun=setup_pte, 17 | subset_fun=two_by_two_subset, 18 | attgt_fun=did_attgt, 19 | xformla=~X) 20 | 21 | expect_equal(res$overall_att$overall.att, 1, tolerance=.5) 22 | dyn_idx <- res$event_study$egt == 0 23 | expect_equal(res$event_study$att.egt[dyn_idx], 1, tolerance=0.5) 24 | 25 | # compare to results from did package 26 | cs_res <- did::att_gt(yname="Y", 27 | gname="G", 28 | tname="period", 29 | idname="id", 30 | data=data, 31 | xformla=~X) 32 | 33 | cs_overall <- did::aggte(cs_res, type="group")$overall.att 34 | expect_equal(res$overall_att$overall.att, cs_overall) 35 | cs_dyn <- did::aggte(cs_res, type="dynamic")$att.egt[dyn_idx] 36 | expect_equal(res$event_study$att.egt[dyn_idx], cs_dyn) 37 | c}) 38 | 39 | test_that("empirical bootstrap", { 40 | sp <- did::reset.sim() 41 | data <- did::build_sim_dataset(sp) 42 | 43 | res <- pte(yname="Y", 44 | gname="G", 45 | tname="period", 46 | idname="id", 47 | data=data, 48 | setup_pte_fun=setup_pte, 49 | subset_fun=two_by_two_subset, 50 | attgt_fun=did_attgt, 51 | xformla=~X, 52 | boot_type="empirical", 53 | biters=10) # just checking that this runs 54 | 55 | expect_equal(res$overall_att$overall.att, 1) 56 | message("this is failing because the names are not correct on the returns 57 | for the empirical bootstrap case") 58 | }) 59 | 60 | test_that("periods that look like years works ok and unbalanced groups", { 61 | data(mpdta) 62 | res <- pte( 63 | yname = "lemp", 64 | gname = "first.treat", 65 | tname = "year", 66 | idname = "countyreal", 67 | data = mpdta, 68 | setup_pte_fun = setup_pte, 69 | subset_fun = two_by_two_subset, 70 | attgt_fun = did_attgt, 71 | xformla = ~ lpop 72 | ) 73 | # this is to test if summary is working // had issues with ife version of this 74 | expect_equal(summary(res)$overall_att$overall_att,-0.0323) 75 | dyn_idx <- summary(res)$event_study[, "Event Time"] == 0 76 | expect_equal(summary(res)$event_study$Estimat[dyn_idx],-0.0201) 77 | 78 | #------------------------------------------------------------------------ 79 | # case where the group variable is named G 80 | #------------------------------------------------------------------------ 81 | data(mpdta) 82 | mpdta$G <- mpdta$first.treat 83 | res <- pte( 84 | yname = "lemp", 85 | gname = "G", 86 | tname = "year", 87 | idname = "countyreal", 88 | data = mpdta, 89 | setup_pte_fun = setup_pte, 90 | subset_fun = two_by_two_subset, 91 | attgt_fun = did_attgt, 92 | xformla = ~ lpop 93 | ) 94 | # this is to test if summary is working // had issues with ife version of this 95 | expect_equal(summary(res)$overall_att$overall_att,-0.0323) 96 | dyn_idx <- summary(res)$event_study[, "Event Time"] == 0 97 | expect_equal(summary(res)$event_study$Estimat[dyn_idx],-0.0201) 98 | }) 99 | 100 | test_that("no formula for covariates is ok", { 101 | sp <- did::reset.sim() 102 | data <- did::build_sim_dataset(sp) 103 | 104 | res <- pte(yname="Y", 105 | gname="G", 106 | tname="period", 107 | idname="id", 108 | data=data, 109 | setup_pte_fun=setup_pte, 110 | subset_fun=two_by_two_subset, 111 | attgt_fun=did_attgt) 112 | 113 | expect_equal(res$overall_att$overall.att, 1, tolerance=.5) 114 | }) -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • pte 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 |
    24 |
    58 | 59 | 60 | 61 | 62 |
    63 |
    64 | 67 | 68 | Content not found. Please use links in the navbar. 69 | 70 |
    71 | 72 | 76 | 77 |
    78 | 79 | 80 | 81 |
    85 | 86 |
    87 |

    88 |

    Site built with pkgdown 2.0.6.

    89 |
    90 | 91 |
    92 |
    93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /man/panel_empirical_bootstrap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/empirical_bootstrap.R 3 | \name{panel_empirical_bootstrap} 4 | \alias{panel_empirical_bootstrap} 5 | \title{panel_empirical_bootstrap} 6 | \usage{ 7 | panel_empirical_bootstrap( 8 | attgt.list, 9 | ptep, 10 | setup_pte_fun, 11 | subset_fun, 12 | attgt_fun, 13 | extra_gt_returns, 14 | ... 15 | ) 16 | } 17 | \arguments{ 18 | \item{attgt.list}{list of attgt results from \code{compute.pte}} 19 | 20 | \item{ptep}{\code{pte_params} object} 21 | 22 | \item{setup_pte_fun}{This is a function that should take in \code{data}, 23 | \code{yname} (the name of the outcome variable in \code{data}), 24 | \code{gname} (the name of the group variable), 25 | \code{idname} (the name of the id variable), 26 | and possibly other arguments such as the significance level \code{alp}, 27 | the number of bootstrap iterations \code{biters}, and how many clusters 28 | for parallel computing in the bootstrap \code{cl}. The key thing that 29 | needs to be figured out in this function is which groups and time periods 30 | ATT(g,t) should be computed in. The function should 31 | return a \code{pte_params} object which contains all of the parameters 32 | passed into the function as well as \code{glist} and \code{tlist} which 33 | should be ordered lists of groups and time periods for ATT(g,t) to be computed. 34 | 35 | This function provides also provides a good place for error handling related 36 | to the types of data that can be handled. 37 | 38 | The \code{pte} package contains the function \code{setup_pte} that is 39 | a lightweight function that basically just takes the data, omits 40 | the never-treated group from \code{glist} but includes all other groups 41 | and drops the first time period. This works in cases where ATT would 42 | be identified in the 2x2 case (i.e., where there are two time periods, 43 | no units are treated in the first period and the identification strategy 44 | "works" with access to a treated and untreated group and untreated 45 | potential outcomes for both groups in the first period) --- for example, 46 | this approach works if DID is the identification strategy.} 47 | 48 | \item{subset_fun}{This is a function that should take in \code{data}, 49 | \code{g} (for group), \code{tp} (for time period), and \code{...} 50 | and be able to return the appropriate \code{data.frame} that can be used 51 | by \code{attgt_fun} to produce ATT(g=g,t=tp). The data frame should 52 | be constructed using \code{gt_data_frame} in order to guarantee that 53 | it has the appropriate columns that identify which group an observation 54 | belongs to, etc.} 55 | 56 | \item{attgt_fun}{This is a function that should work in the case where 57 | there is a single group and the "right" number of time periods to 58 | recover an estimate of the ATT. For example, in the contest of 59 | difference in differences, it would need to work for a single group, 60 | find the appropriate comparison group (untreated units), find the right 61 | time periods (pre- and post-treatment), and then recover an estimate 62 | of ATT for that group. It will be called over and over separately 63 | by groups and by time periods to compute ATT(g,t)'s. 64 | 65 | The function needs to work in a very specific way. It should take in the 66 | arguments: \code{data}, \code{...}. \code{data} should be constructed 67 | using the function \code{gt_data_frame} which checks to make sure 68 | that \code{data} has the correct columns defined. 69 | \code{...} are additional arguments (such as 70 | formulas for covariates) that \code{attgt_fun} needs. From these arguments 71 | \code{attgt_fun} must return a list with element \code{ATT} containing the 72 | group-time average treatment effect for that group and that time period. 73 | 74 | If \code{attgt_fun} returns an influence function (which should be provided 75 | in a list element named \code{inf_func}), then the code will use the 76 | multiplier bootstrap to compute standard errors for group-time average 77 | treatment effects, an overall treatment effect parameter, and a dynamic 78 | treatment effect parameter (i.e., event study parameter). If 79 | \code{attgt_fun} does not return an influence function, then the same 80 | objects will be computed using the empirical bootstrap. This is usually 81 | (perhaps substantially) easier to code, but also will usually be (perhaps 82 | substantially) computationally slower.} 83 | 84 | \item{extra_gt_returns}{A place to return anything extra from particular 85 | group-time average treatment effect calculations. For DID, this might 86 | be something like propensity score estimates, regressions of untreated 87 | potential outcomes on covariates. For ife, this could be something 88 | like the first step regression 2sls estimates. This argument is also 89 | potentially useful for debugging.} 90 | 91 | \item{...}{extra arguments that can be passed to create the correct subsets 92 | of the data (depending on \code{subset_fun}), to estimate group time 93 | average treatment effects (depending on \code{attgt_fun}), or to 94 | aggregating treatment effects (particularly useful are \code{min_e}, 95 | \code{max_e}, and \code{balance_e} arguments to event study aggregations)} 96 | } 97 | \value{ 98 | \code{pte_emp_boot} object 99 | } 100 | \description{ 101 | Computes empirical bootstrap pointwise standard errors 102 | } 103 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | Authors and Citation • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 |
    43 | 46 | 47 | 48 |
    • 49 |

      Brantly Callaway. Author, maintainer. 50 |

      51 |
    • 52 |
    53 |
    54 |
    55 |

    Citation

    56 | Source: DESCRIPTION 57 |
    58 |
    59 | 60 | 61 |

    Callaway B (2023). 62 | pte: Panel Treatment Effects. 63 | R package version 0.0.0.9000, https://github.com/bcallaway11/pte. 64 |

    65 |
    @Manual{,
    66 |   title = {pte: Panel Treatment Effects},
    67 |   author = {Brantly Callaway},
    68 |   year = {2023},
    69 |   note = {R package version 0.0.0.9000},
    70 |   url = {https://github.com/bcallaway11/pte},
    71 | }
    72 | 73 |
    74 | 75 |
    76 | 77 | 78 | 79 |
    82 | 83 |
    84 |

    Site built with pkgdown 2.0.6.

    85 |
    86 | 87 |
    88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /docs/reference/ggpte.html: -------------------------------------------------------------------------------- 1 | 2 | ggpte — ggpte • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    Simple event study plots for panel treatment effects

    50 |
    51 | 52 |
    53 |
    ggpte(pte_results)
    54 |
    55 | 56 |
    57 |

    Arguments

    58 |
    pte_results
    59 |

    A pte_results object

    60 | 61 |
    62 | 63 |
    64 | 67 |
    68 | 69 | 70 |
    73 | 74 |
    75 |

    Site built with pkgdown 2.0.6.

    76 |
    77 | 78 |
    79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /docs/reference/process_att_gt.html: -------------------------------------------------------------------------------- 1 | 2 | process_att_gt — process_att_gt • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    process attgt results when influence function is available

    50 |
    51 | 52 |
    53 |
    process_att_gt(att_gt_results, ptep)
    54 |
    55 | 56 |
    57 |

    Arguments

    58 |
    att_gt_results
    59 |

    ATT(g,t)'s

    60 | 61 | 62 |
    ptep
    63 |

    pte_params object

    64 | 65 |
    66 | 67 |
    68 | 71 |
    72 | 73 | 74 |
    77 | 78 |
    79 |

    Site built with pkgdown 2.0.6.

    80 |
    81 | 82 |
    83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /docs/reference/print.pte_results.html: -------------------------------------------------------------------------------- 1 | 2 | print.pte_results — print.pte_results • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    prints value of a pte_results object

    50 |
    51 | 52 |
    53 |
    # S3 method for pte_results
    54 | print(x, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    x
    60 |

    a pte_results object

    61 | 62 | 63 |
    ...
    64 |

    extra arguments

    65 | 66 |
    67 | 68 |
    69 | 72 |
    73 | 74 | 75 |
    78 | 79 |
    80 |

    Site built with pkgdown 2.0.6.

    81 |
    82 | 83 |
    84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/summary.pte_results.html: -------------------------------------------------------------------------------- 1 | 2 | summary.pte_results — summary.pte_results • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    A function to summarize pte results.

    50 |
    51 | 52 |
    53 |
    # S3 method for pte_results
    54 | summary(object, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    object
    60 |

    an pte_results object

    61 | 62 | 63 |
    ...
    64 |

    other arguments

    65 | 66 |
    67 | 68 |
    69 | 72 |
    73 | 74 | 75 |
    78 | 79 |
    80 |

    Site built with pkgdown 2.0.6.

    81 |
    82 | 83 |
    84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/print.group_time_att.html: -------------------------------------------------------------------------------- 1 | 2 | print.group_time_att — print.group_time_att • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    prints value of a group_time_att object

    50 |
    51 | 52 |
    53 |
    # S3 method for group_time_att
    54 | print(x, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    x
    60 |

    a group_time_att object

    61 | 62 | 63 |
    ...
    64 |

    extra arguments

    65 | 66 |
    67 | 68 |
    69 | 72 |
    73 | 74 | 75 |
    78 | 79 |
    80 |

    Site built with pkgdown 2.0.6.

    81 |
    82 | 83 |
    84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/pte_results.html: -------------------------------------------------------------------------------- 1 | 2 | pte_results — pte_results • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    class for holding pte results

    50 |
    51 | 52 |
    53 |
    pte_results(att_gt, overall_att, event_study, ptep)
    54 |
    55 | 56 |
    57 |

    Arguments

    58 |
    att_gt
    59 |

    attgt results

    60 | 61 | 62 |
    overall_att
    63 |

    overall_att results

    64 | 65 | 66 |
    event_study
    67 |

    event_study results

    68 | 69 | 70 |
    ptep
    71 |

    pte_params object

    72 | 73 |
    74 | 75 |
    76 | 79 |
    80 | 81 | 82 |
    85 | 86 |
    87 |

    Site built with pkgdown 2.0.6.

    88 |
    89 | 90 |
    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/reference/mboot2.html: -------------------------------------------------------------------------------- 1 | 2 | mboot2 — mboot2 • pte 7 | 8 | 9 |
    10 |
    38 | 39 | 40 | 41 |
    42 |
    43 | 48 | 49 |
    50 |

    function for using multiplier bootstrap to conduct 51 | inference

    52 |
    53 | 54 |
    55 |
    mboot2(inffunc, biters = 1000, alp = 0.05)
    56 |
    57 | 58 |
    59 |

    Arguments

    60 |
    inffunc
    61 |

    influence function matrix

    62 | 63 | 64 |
    biters
    65 |

    number of bootstrap iterations; default is 100

    66 | 67 | 68 |
    alp
    69 |

    significance level; default is 0.05

    70 | 71 |
    72 | 73 |
    74 | 77 |
    78 | 79 | 80 |
    83 | 84 |
    85 |

    Site built with pkgdown 2.0.6.

    86 |
    87 | 88 |
    89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /docs/reference/summary.group_time_att.html: -------------------------------------------------------------------------------- 1 | 2 | summary.group_time_att — summary.group_time_att • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    prints a summary of a group_time_att object

    50 |
    51 | 52 |
    53 |
    # S3 method for group_time_att
    54 | summary(object, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    object
    60 |

    an group_time_att object

    61 | 62 | 63 |
    ...
    64 |

    extra arguments

    65 | 66 |
    67 | 68 |
    69 | 72 |
    73 | 74 | 75 |
    78 | 79 |
    80 |

    Site built with pkgdown 2.0.6.

    81 |
    82 | 83 |
    84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/print.summary.pte_results.html: -------------------------------------------------------------------------------- 1 | 2 | print.summary.pte_results — print.summary.pte_results • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    prints value of a summary.pte_results object

    50 |
    51 | 52 |
    53 |
    # S3 method for summary.pte_results
    54 | print(x, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    x
    60 |

    a summary.pte_results object

    61 | 62 | 63 |
    ...
    64 |

    extra arguments

    65 | 66 |
    67 | 68 |
    69 | 72 |
    73 | 74 | 75 |
    78 | 79 |
    80 |

    Site built with pkgdown 2.0.6.

    81 |
    82 | 83 |
    84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /docs/reference/summary.pte_emp_boot.html: -------------------------------------------------------------------------------- 1 | 2 | summary.pte_emp_boot — summary.pte_emp_boot • pte 6 | 7 | 8 |
    9 |
    37 | 38 | 39 | 40 |
    41 |
    42 | 47 | 48 |
    49 |

    Summary for pte_emp_boot object

    50 |
    51 | 52 |
    53 |
    # S3 method for pte_emp_boot
    54 | summary(object, ...)
    55 |
    56 | 57 |
    58 |

    Arguments

    59 |
    object
    60 |

    a pte_emp_boot object

    61 | 62 | 63 |
    ...
    64 |

    additional function arguments

    65 | 66 |
    67 |
    68 |

    Value

    69 | 70 | 71 |

    summary.pte_results object

    72 |
    73 | 74 |
    75 | 78 |
    79 | 80 | 81 |
    84 | 85 |
    86 |

    Site built with pkgdown 2.0.6.

    87 |
    88 | 89 |
    90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/reference/qtt_pte_aggregations.html: -------------------------------------------------------------------------------- 1 | 2 | qtt_pte_aggregations — qtt_pte_aggregations • pte 7 | 8 | 9 |
    10 |
    38 | 39 | 40 | 41 |
    42 |
    43 | 48 | 49 |
    50 |

    Aggregate group-time distributions into qtt versions of 51 | overall, group, and dynamic effects.

    52 |
    53 | 54 |
    55 |
    qtt_pte_aggregations(attgt.list, ptep, extra_gt_returns)
    56 |
    57 | 58 |
    59 |

    Arguments

    60 |
    attgt.list
    61 |

    list of attgt results from compute.pte

    62 | 63 | 64 |
    ptep
    65 |

    pte_params object

    66 | 67 |
    68 |
    69 |

    Value

    70 | 71 | 72 |

    pte_emp_boot object

    73 |
    74 | 75 |
    76 | 79 |
    80 | 81 | 82 |
    85 | 86 |
    87 |

    Site built with pkgdown 2.0.6.

    88 |
    89 | 90 |
    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/reference/qott_pte_aggregations.html: -------------------------------------------------------------------------------- 1 | 2 | qott_pte_aggregations — qott_pte_aggregations • pte 7 | 8 | 9 |
    10 |
    38 | 39 | 40 | 41 |
    42 |
    43 | 48 | 49 |
    50 |

    Aggregate group-time distribution of the treatment effect into 51 | overall, group, and dynamic effects.

    52 |
    53 | 54 |
    55 |
    qott_pte_aggregations(attgt.list, ptep, extra_gt_returns)
    56 |
    57 | 58 |
    59 |

    Arguments

    60 |
    attgt.list
    61 |

    list of attgt results from compute.pte

    62 | 63 | 64 |
    ptep
    65 |

    pte_params object

    66 | 67 |
    68 |
    69 |

    Value

    70 | 71 | 72 |

    pte_emp_boot object

    73 |
    74 | 75 |
    76 | 79 |
    80 | 81 | 82 |
    85 | 86 |
    87 |

    Site built with pkgdown 2.0.6.

    88 |
    89 | 90 |
    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/reference/gt_data_frame.html: -------------------------------------------------------------------------------- 1 | 2 | gt_data_frame — gt_data_frame • pte 8 | 9 | 10 |
    11 |
    39 | 40 | 41 | 42 |
    43 |
    44 | 49 | 50 |
    51 |

    function to take in a data.frame, check if it has the right 52 | columns to be used to calculate a group-time average treatment effect, 53 | and sets the class of the data.frame to include gt_data_frame

    54 |
    55 | 56 |
    57 |
    gt_data_frame(data)
    58 |
    59 | 60 |
    61 |

    Arguments

    62 |
    data
    63 |

    data that will be checked to see if has right format for 64 | computing group-time average treatment effects

    65 | 66 |
    67 |
    68 |

    Value

    69 | 70 | 71 |

    gt_data_frame object

    72 |
    73 | 74 |
    75 | 78 |
    79 | 80 | 81 |
    84 | 85 |
    86 |

    Site built with pkgdown 2.0.6.

    87 |
    88 | 89 |
    90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /docs/reference/orig2t.html: -------------------------------------------------------------------------------- 1 | 2 | orig2t — orig2t • pte 9 | 10 | 11 |
    12 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 50 | 51 |
    52 |

    A helper function to switch from original time periods to 53 | "new" time periods (which are just time periods going from 1 to total 54 | number of available periods). This allows for periods not being 55 | exactly spaced apart by 1.

    56 |
    57 | 58 |
    59 |
    orig2t(orig, original_time.periods)
    60 |
    61 | 62 |
    63 |

    Arguments

    64 |
    original_time.periods
    65 |

    vector containing all original time periods.

    66 | 67 |
    68 |
    69 |

    Value

    70 | 71 | 72 |

    new time period converted from original time period

    73 |
    74 | 75 |
    76 | 79 |
    80 | 81 | 82 |
    85 | 86 |
    87 |

    Site built with pkgdown 2.0.6.

    88 |
    89 | 90 |
    91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /docs/reference/t2orig.html: -------------------------------------------------------------------------------- 1 | 2 | t2orig — t2orig • pte 8 | 9 | 10 |
    11 |
    39 | 40 | 41 | 42 |
    43 |
    44 | 49 | 50 |
    51 |

    A helper function to switch from "new" t values to 52 | original t values. This allows for periods not being exactly spaced 53 | apart by 1.

    54 |
    55 | 56 |
    57 |
    t2orig(t, original_time.periods)
    58 |
    59 | 60 |
    61 |

    Arguments

    62 |
    t
    63 |

    a particular time period to convert back to original time 64 | periods.

    65 | 66 | 67 |
    original_time.periods
    68 |

    vector containing all original time periods.

    69 | 70 |
    71 |
    72 |

    Value

    73 | 74 | 75 |

    original time period converted from new time period

    76 |
    77 | 78 |
    79 | 82 |
    83 | 84 | 85 |
    88 | 89 |
    90 |

    Site built with pkgdown 2.0.6.

    91 |
    92 | 93 |
    94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /R/process_att_gt.R: -------------------------------------------------------------------------------- 1 | #' @title process_att_gt 2 | #' 3 | #' @description process attgt results when influence function is available 4 | #' 5 | #' @param att_gt_results ATT(g,t)'s 6 | #' @inheritParams pte_results 7 | #' 8 | #' @export 9 | process_att_gt <- function(att_gt_results, ptep) { 10 | # extract ATT(g,t) and influence functions 11 | attgt.list <- att_gt_results$attgt.list 12 | inffunc <- att_gt_results$inffunc 13 | 14 | # a bit of a hack way to get standard errors 15 | # with a universal base period when some ATT(g,t)'s 16 | # are 0 by construction and have no s.e.'s / inf. func. 17 | # if (isTRUE(ptep$base_period == "universal")) { 18 | # set0cols <- sapply(1:ncol(inffunc), function(i) { 19 | # (all(is.na(inffunc[,i]))) 20 | # }) 21 | # inffunc[,set0cols] <- 0 22 | # } 23 | 24 | # process results 25 | attgt.results <- do.call("rbind.data.frame", attgt.list) 26 | att <- attgt.results$att 27 | group <- attgt.results$group 28 | time.period <- attgt.results$time.period 29 | extra_gt_returns <- att_gt_results$extra_gt_returns 30 | 31 | #----------------------------------------------------------------------------- 32 | # analytical standard errors 33 | # * estimate variance 34 | # this is analogous to cluster robust standard errors that 35 | # are clustered at the unit level 36 | #----------------------------------------------------------------------------- 37 | n <- nrow(inffunc) 38 | V <- Matrix::t(inffunc) %*% inffunc / n 39 | se <- sqrt(Matrix::diag(V) / n) 40 | cband <- ptep$cband 41 | alp <- ptep$alp 42 | 43 | # critical value from N(0,1), for pointwise 44 | cval <- qnorm(1 - alp / 2) 45 | 46 | # multiplier bootstrap results 47 | bout <- mboot2(inffunc, alp = alp) 48 | 49 | if (cband) cval <- bout$crit_val 50 | 51 | #----------------------------------------------------------------------------- 52 | # compute Wald pre-test 53 | #----------------------------------------------------------------------------- 54 | # select which periods are pre-treatment 55 | pre <- which(group > time.period) 56 | 57 | # pseudo-atts in pre-treatment periods 58 | preatt <- as.matrix(att[pre]) 59 | 60 | # covariance matrix of pre-treatment atts 61 | preV <- as.matrix(V[pre, pre]) 62 | 63 | # check if there are actually any pre-treatment periods 64 | W <- NULL 65 | Wpval <- NULL 66 | if (length(preV) == 0) { 67 | message("No pre-treatment periods to test") 68 | } else if (sum(is.na(preV))) { 69 | warning("Not returning pre-test Wald statistic due to NA pre-treatment values") 70 | } else if (rcond(preV) <= .Machine$double.eps) { 71 | # singluar covariance matrix for pre-treatment periods 72 | warning("Not returning pre-test Wald statistic due to singular covariance matrix") 73 | } else { 74 | # everything is working... 75 | W <- n * t(preatt) %*% solve(preV) %*% preatt 76 | q <- length(pre) # number of restrictions 77 | Wpval <- round(1 - pchisq(W, q), 5) 78 | } 79 | 80 | # convert tlist and glist to be compatible with did::aggte 81 | 82 | # from "new" time to "original" time 83 | original_time.periods <- sort(unique(ptep$data[, ptep$tname])) 84 | if (!all(ptep$tlist %in% original_time.periods)) { 85 | ptep$tlist <- sapply(ptep$tlist, 86 | BMisc::t2orig, 87 | original_time.periods = original_time.periods 88 | ) 89 | ptep$glist <- sapply(ptep$glist, 90 | BMisc::t2orig, 91 | original_time.periods = original_time.periods 92 | ) 93 | group <- sapply(group, 94 | BMisc::t2orig, 95 | original_time.periods = original_time.periods 96 | ) 97 | time.period <- sapply(time.period, 98 | BMisc::t2orig, 99 | original_time.periods = original_time.periods 100 | ) 101 | extra_gt_returns <- lapply( 102 | extra_gt_returns, 103 | function(egr) { 104 | egr$group <- BMisc::t2orig(egr$group, original_time.periods) 105 | egr$time.period <- BMisc::t2orig(egr$time.period, original_time.periods) 106 | egr 107 | } 108 | ) 109 | } 110 | 111 | # set groups to be untreated so that we do not drop them later (would be better to have this in 112 | # aggte code, but no changes there. The only place where I know this is used is for staggered_ife 113 | # ptep$data[,ptep$gname] <- ifelse( !(ptep$data[,ptep$gname] %in% ptep$glist), 0, ptep$data[,ptep$gname]) 114 | if (is.null(ptep$weightsname)) { 115 | ptep$data$.w <- 1 116 | } else { 117 | ptep$data$.w <- ptep$data[, ptep$weightsname] 118 | } 119 | 120 | # Return list for ATT(g,t) 121 | return(group_time_att(group = group, time.period = time.period, att = att, V_analytical = V, se = bout$boot_se, crit_val = cval, inf_func = inffunc, n = n, W = W, Wpval = Wpval, cband = cband, alp = alp, ptep = ptep, extra_gt_returns = extra_gt_returns)) 122 | } 123 | 124 | #' @title mboot2 125 | #' 126 | #' @description function for using multiplier bootstrap to conduct 127 | #' inference 128 | #' 129 | #' @param inffunc influence function matrix 130 | #' @inheritParams pte 131 | #' 132 | #' @export 133 | mboot2 <- function(inffunc, biters = 1000, alp = .05) { 134 | n <- nrow(as.matrix(inffunc)) 135 | 136 | # run the multiplier bootstrap 137 | bout <- lapply(1:biters, function(b) { 138 | # draw from -1,1 each with p=1/2 139 | Ub <- sample(c(-1, 1), size = n, replace = TRUE) 140 | Rb <- sqrt(n) * (apply(Ub * inffunc, 2, mean)) 141 | Rb 142 | }) 143 | bres <- do.call("rbind", bout) 144 | 145 | # bootstrap compatible standard errors 146 | boot_se <- apply( 147 | bres, 2, 148 | function(b) { 149 | (quantile(b, .75, type = 1, na.rm = T) - 150 | quantile(b, .25, type = 1, na.rm = T)) / (qnorm(.75) - qnorm(.25)) 151 | } 152 | ) / sqrt(n) 153 | 154 | # bootstrap t-stat (i.e., sup-t) 155 | bT <- apply(bres, 1, function(b) max(abs(b / boot_se), na.rm = TRUE)) / sqrt(n) 156 | 157 | # new critical value for uniform confidence bands 158 | crit_val <- quantile(bT, 1 - alp, type = 1, na.rm = T) 159 | if (crit_val < qnorm(1 - alp / 2)) { 160 | warning("critical value for uniform confidence band is somehow smaller than 161 | critical value for pointwise confidence interval...using pointwise 162 | confidence interal") 163 | crit_val <- cval <- qnorm(1 - alp / 2) 164 | } 165 | 166 | return(list(boot_se = boot_se, crit_val = crit_val)) 167 | } 168 | -------------------------------------------------------------------------------- /docs/reference/attgt_noif.html: -------------------------------------------------------------------------------- 1 | 2 | attgt_noif — attgt_noif • pte 7 | 8 | 9 |
    10 |
    38 | 39 | 40 | 41 |
    42 |
    43 | 48 | 49 |
    50 |

    Class for holding group-time average treatment effects 51 | which don't include influence functions

    52 |
    53 | 54 |
    55 |
    attgt_noif(attgt, extra_gt_returns = NULL)
    56 |
    57 | 58 |
    59 |

    Arguments

    60 |
    attgt
    61 |

    group-time average treatment effect

    62 | 63 | 64 |
    extra_gt_returns
    65 |

    A place to return anything extra from particular 66 | group-time average treatment effect calculations. For DID, this might 67 | be something like propensity score estimates, regressions of untreated 68 | potential outcomes on covariates. For ife, this could be something 69 | like the first step regression 2sls estimates. This argument is also 70 | potentially useful for debugging.

    71 | 72 |
    73 |
    74 |

    Value

    75 | 76 | 77 |

    attgt_noif object

    78 |
    79 | 80 |
    81 | 84 |
    85 | 86 | 87 |
    90 | 91 |
    92 |

    Site built with pkgdown 2.0.6.

    93 |
    94 | 95 |
    96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /docs/reference/attgt_pte_aggregations.html: -------------------------------------------------------------------------------- 1 | 2 | attgt_pte_aggregations — attgt_pte_aggregations • pte 9 | 10 | 11 |
    12 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 50 | 51 |
    52 |

    Aggregate group-time average treatment effects into 53 | overall, group, and dynamic effects. This function is only used 54 | for (i) computing standard errors using the empirical bootstrap, 55 | and (ii) combining distributions at the (g,t) level

    56 |
    57 | 58 |
    59 |
    attgt_pte_aggregations(attgt.list, ptep)
    60 |
    61 | 62 |
    63 |

    Arguments

    64 |
    attgt.list
    65 |

    list of attgt results from compute.pte

    66 | 67 | 68 |
    ptep
    69 |

    pte_params object

    70 | 71 |
    72 |
    73 |

    Value

    74 | 75 | 76 |

    pte_emp_boot object

    77 |
    78 | 79 |
    80 | 83 |
    84 | 85 | 86 |
    89 | 90 |
    91 |

    Site built with pkgdown 2.0.6.

    92 |
    93 | 94 |
    95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /R/subset_functions.R: -------------------------------------------------------------------------------- 1 | #' @title two_by_two_subset 2 | #' 3 | #' @description A function for computing a 2x2 subset of original data. 4 | #' This is the subset with post treatment periods separately for the 5 | #' treated group and comparison group and pre-treatment periods in the period 6 | #' immediately before the treated group became treated. 7 | #' 8 | #' @inheritParams pte_params 9 | #' 10 | #' @param data the full dataset 11 | #' @param g the current group 12 | #' @param tp the current time period 13 | #' @param control_group whether to use "notyettreated" (default) or 14 | #' "nevertreated" 15 | #' @param anticipation the number of periods of anticipation (i.e., number 16 | #' of periods before the treatment happens where the treatment can "already" 17 | #' affect the outcome) 18 | #' @param ... extra arguments to get the subset correct 19 | #' 20 | #' @return list that contains correct subset of data, \code{n1} 21 | #' number of observations 22 | #' in this subset, and \code{disidx} a vector of the correct ids for this 23 | #' subset. 24 | #' 25 | #' @export 26 | two_by_two_subset <- function(data, 27 | g, 28 | tp, 29 | control_group = "notyettreated", 30 | anticipation = 0, 31 | base_period = "varying", 32 | ...) { 33 | # get the correct "base" period for this group 34 | main.base.period <- g - anticipation - 1 35 | 36 | #---------------------------------------------------- 37 | if (base_period == "varying") { 38 | # if it's a pre-treatment time period (used for the 39 | # pre-test, we need to adjust the base period) 40 | 41 | # group not treated yet 42 | if (tp < (g - anticipation)) { 43 | # move to earlier period 44 | # not going to include anticipation here 45 | base.period <- tp - 1 46 | } else { 47 | # this is a post-treatment period 48 | base.period <- main.base.period 49 | } 50 | } else { 51 | base.period <- main.base.period 52 | } 53 | #---------------------------------------------------- 54 | 55 | #---------------------------------------------------- 56 | # collect the right subset of the data 57 | 58 | # get group g and not-yet-treated group 59 | if (control_group == "notyettreated") { 60 | this.data <- subset(data, G == g | G > tp | G == 0) 61 | } else { 62 | # use never treated group 63 | this.data <- subset(data, G == g | G == 0) 64 | } 65 | 66 | # get current period and base period data 67 | this.data <- subset(this.data, period == tp | period == base.period) 68 | 69 | # variable to keep track of pre/post periods 70 | this.data$name <- ifelse(this.data$period == tp, "post", "pre") 71 | 72 | # variable to indicate local treatment status 73 | this.data$D <- 1 * (this.data$G == g) 74 | 75 | # make this.data into gt_data_frame object 76 | this.data <- gt_data_frame(this.data) 77 | 78 | # number of observations used for this (g,t) 79 | n1 <- length(unique(this.data$id)) 80 | disidx <- unique(data$id) %in% unique(this.data$id) 81 | 82 | list(gt_data = this.data, n1 = n1, disidx = disidx) 83 | } 84 | 85 | 86 | #' @title keep_all_untreated_subset 87 | #' 88 | #' @description A function that takes an original data set and keeps all 89 | #' pre-treatment data for all groups. For group g, it also includes data 90 | #' for the current period. 91 | #' 92 | #' Also, note that if `tp` is still a pre-treatment period for group g, 93 | #' then periods after `tp` will also be dropped for group g. This is a 94 | #' design choice and is useful especially for estimating placebo 95 | #' group-time average treatment effects in pre-treatment periods. 96 | #' 97 | #' A main use case for this function is to compute ATT(g,t)'s using a global 98 | #' estimation strategy such as imputation in Gardner (2022). 99 | #' 100 | #' @inheritParams two_by_two_subset 101 | #' 102 | #' @return all data but in correct format for computing ATT(g,t) 103 | #' 104 | #' @export 105 | keep_all_untreated_subset <- function(data, g, tp, ...) { 106 | # drop post-treatment observations that are not in group g 107 | # this creates the same sort of unbalanced panel data set 108 | # used in imputation papers. 109 | data$.treat <- 1 * ((data$G <= data$period) & (data$G != 0)) 110 | this.data <- subset(data, (.treat == 0) | (G == g)) 111 | 112 | # This line drops any periods after the "current" period too (even 113 | # if these are untreated) for group g. 114 | # This is to deal with pre-treatment periods 115 | # where it seems ambiguous/confusing what exactly to do and rules 116 | # out that later periods will be used to estimate the model for untreated 117 | # potential outcomes using group g. 118 | this.data <- subset(this.data, !(G == g & period > tp)) 119 | 120 | # variable to keep track of pre/post periods 121 | this.data$name <- ifelse(this.data$period == tp, "post", "pre") 122 | 123 | this.data$D <- 1 * ((this.data$G == g) & this.data$period >= tp) 124 | n1 <- length(unique(this.data$id)) 125 | disidx <- unique(data$id) %in% unique(this.data$id) 126 | 127 | list(gt_data = this.data, n1 = n1, disidx = disidx) 128 | } 129 | 130 | 131 | #' @title keep_all_pretreatment_subset 132 | #' 133 | #' @description A function that takes an original data set and keeps all 134 | #' data for all groups that are not-yet-treated by period `tp` as well 135 | #' as for group `g`. 136 | #' 137 | #' In particular, this keeps more data than functions like `two_by_two` 138 | #' subset that use a fixed base period. 139 | #' 140 | #' A main use case for this function is the interactive fixed effects approach 141 | #' proposed in Callaway and Tsyawo (2023). 142 | #' 143 | #' @inheritParams two_by_two_subset 144 | #' @param ... additional arguments 145 | #' 146 | #' @return all data but in correct format for computing ATT(g,t) 147 | #' 148 | #' @export 149 | keep_all_pretreatment_subset <- function(data, g, tp, ...) { 150 | this.data <- subset(data, period <= tp) 151 | # keep group g, not-yet-treated groups, and never-treated group 152 | this.data <- subset(this.data, (G == g) | (G > tp) | (G == 0)) 153 | 154 | # variable to keep track of pre/post periods 155 | this.data$name <- ifelse(this.data$period == tp, "post", "pre") 156 | 157 | this.data$D <- 1 * ((this.data$G == g) & this.data$period >= tp) 158 | n1 <- length(unique(this.data$id)) 159 | disidx <- unique(data$id) %in% unique(this.data$id) 160 | 161 | list(gt_data = this.data, n1 = n1, disidx = disidx) 162 | } 163 | -------------------------------------------------------------------------------- /docs/reference/attgt_if.html: -------------------------------------------------------------------------------- 1 | 2 | attgt_if — attgt_if • pte 7 | 8 | 9 |
    10 |
    38 | 39 | 40 | 41 |
    42 |
    43 | 48 | 49 |
    50 |

    Class for holding group-time average treatment effects 51 | along with their influence function

    52 |
    53 | 54 |
    55 |
    attgt_if(attgt, inf_func, extra_gt_returns = NULL)
    56 |
    57 | 58 |
    59 |

    Arguments

    60 |
    attgt
    61 |

    group-time average treatment effect

    62 | 63 | 64 |
    inf_func
    65 |

    influence function

    66 | 67 | 68 |
    extra_gt_returns
    69 |

    A place to return anything extra from particular 70 | group-time average treatment effect calculations. For DID, this might 71 | be something like propensity score estimates, regressions of untreated 72 | potential outcomes on covariates. For ife, this could be something 73 | like the first step regression 2sls estimates. This argument is also 74 | potentially useful for debugging.

    75 | 76 |
    77 |
    78 |

    Value

    79 | 80 | 81 |

    attgt_if object

    82 |
    83 | 84 |
    85 | 88 |
    89 | 90 | 91 |
    94 | 95 |
    96 |

    Site built with pkgdown 2.0.6.

    97 |
    98 | 99 |
    100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /docs/reference/two_by_two_subset.html: -------------------------------------------------------------------------------- 1 | 2 | two_by_two_subset — two_by_two_subset • pte 9 | 10 | 11 |
    12 |
    40 | 41 | 42 | 43 |
    44 |
    45 | 50 | 51 |
    52 |

    A function for computing a 2x2 subset of original data. 53 | This is the subset with post treatment periods separately for the 54 | treated group and comparison group and pre-treatment periods in the period 55 | immediately before the treated group became treated.

    56 |
    57 | 58 |
    59 |
    two_by_two_subset(data, g, tp, control_group = "notyettreated", ...)
    60 |
    61 | 62 |
    63 |

    Arguments

    64 |
    data
    65 |

    the full dataset

    66 | 67 | 68 |
    g
    69 |

    the current group

    70 | 71 | 72 |
    tp
    73 |

    the current time period

    74 | 75 | 76 |
    control_group
    77 |

    whether to use "notyettreated" (default) or 78 | "nevertreated"

    79 | 80 | 81 |
    ...
    82 |

    extra arguments to get the subset correct

    83 | 84 |
    85 |
    86 |

    Value

    87 | 88 | 89 |

    list that contains correct subset of data, n1

    90 | 91 | 92 |

    number of observations 93 | in this subset, and disidx a vector of the correct ids for this 94 | subset.

    95 |
    96 | 97 |
    98 | 101 |
    102 | 103 | 104 |
    113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | --------------------------------------------------------------------------------