---
title: "LRErdd: Regression Discontinuity Designs as Local Randomized Experiments"
author: "Ibon Tamayo, Alessandra Mattei, Fabrizia Mealli and Marie-Abele Bind"
date: "`r Sys.Date()`"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{LRErdd: Regression Discontinuity Designs as Local Randomized Experiments}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 4.5,
  warning = FALSE,
  message = FALSE
)
set.seed(27)
```

## Introduction

The **LRErdd** package provides a set of functions for the design and analysis
of Regression Discontinuity (RD) Designs as *local randomized experiments*
within the potential outcome approach, as formalized in Li, Mattei and Mealli
(2015).

The key insight underlying this approach is that, under a local randomization
assumption, valid causal inference can be drawn for subpopulations of treated
and control units whose realized values of the forcing variable fall in a
neighborhood of the threshold and who have similar background characteristics.

The package supports the two phases of an RD study:

* **Design phase.** A subset of functions focuses on the selection of suitable
  subpopulations around the threshold for which valid causal inference can be
  drawn. These functions provide summary statistics of pre- and post-treatment
  variables by treatment status, and select subpopulations where pre-treatment
  variables are well balanced between treatment groups, using
  randomization-based tests with adjustment for multiplicities. Functions for
  a visual inspection of the results are also provided.

* **Analysis phase.** A second set of functions draws inference on causal
  effects for the selected subpopulations using randomization-based modes of
  inference. Specifically, the Fisher Exact p-value (FEP) and Neyman
  approaches are implemented for the analysis of both *sharp* and *fuzzy* RD
  designs.

There are two ways of working with the package:

1. Programmatically in R, through the `RegressionDiscontinuityClass` R6 class,
   which encapsulates the whole workflow. This option is illustrated in this
   vignette and is the recommended one for larger datasets and reproducible
   analyses.
2. Interactively, through a user-friendly Shiny application shipped with the
   package (see the last section of this vignette).

## Installation

```{r install, eval = FALSE}
install.packages("LRErdd")
```

```{r load}
library(LRErdd)
```

## The case study: Italian university grants and student dropout

We illustrate the workflow with data from an Italian study concerning the
effects of university grants on student dropout (Li, Mattei and Mealli, 2015).
Eligibility for the grant is determined by a measure of the economic situation
of the student's family (`S`, the forcing variable) falling below a threshold
of 15,000 euros, which makes it a natural regression discontinuity design.
Because not all eligible students applied for and received the grant, the
design is *fuzzy*: the treatment received (`W`) does not coincide with the
eligibility status (`Z`).

```{r data}
data(grants)
dim(grants)
head(grants[, c("S", "Z", "A", "W", "dropout", "sex", "hsgrade")])
```

The dataset contains information on 15,984 students. The main variables are
the forcing variable `S`, the eligibility indicator `Z`, the grant application
indicator `A`, the treatment received `W`, and the outcome `dropout` (1 if the
student dropped out). The remaining columns are pre-treatment covariates (sex,
high school type and grade, cohort, university, and field of study).

## Creating a `RegressionDiscontinuityClass` object

The whole analysis is driven by an object of class
`RegressionDiscontinuityClass`. To create it, we need the dataset (a data
frame), the name of the forcing variable, the threshold, whether the treatment
group is below (`"lower"`) or above (`"upper"`) the threshold, and the vector
of covariate names used to assess balance.

```{r create}
# Covariates of interest
cov <- c("HSTech", "hsgrade", "Y2005")

rdo <- RegressionDiscontinuityClass$new(
  data       = grants,
  forcing    = "S",
  threshold  = 15000,
  Z1S1       = "lower",
  covariates = cov
)
```

The `full_print()` method summarizes the information stored in the object:

```{r fullprint}
rdo$full_print()
```

## Design phase

### Summary statistics

The `summary_statistics_mean()` method reports the mean of each selected
covariate, overall and by treatment assignment status, together with the group
sizes:

```{r summarystats}
rdo$summary_statistics_mean()
```

### Bandwidth selection

The `bandwidth_selection()` method evaluates the influence of a candidate
bandwidth around the threshold on the balance of the covariates. Three ways of
defining the range are available through the `typerange` argument:

* `"percentage"`: considering the range of the forcing variable as 100%, the
  bandwidth is defined as a percentage of that range.
* `"balunit"`: a symmetric bandwidth is defined by its total width in the
  units of the forcing variable.
* `"unbalunit"`: an asymmetric bandwidth, defined by the lower and upper
  bounds provided in `range_value`.

The method returns the number of selected records with the limits of the
selected range, a table with initial and bandwidth-specific p-values (raw and
adjusted for multiplicity) from randomization-based balance tests, and,
optionally, a histogram of the forcing variable with the threshold (black) and
the selected limits (red):

```{r bandwidth}
rdo$bandwidth_selection(
  typerange   = "percentage",
  range_value = 25,
  num_it      = 100,
  plot        = TRUE
)
```

### Distribution of a covariate before and after the selection

The `distribution_plot()` method compares the distribution of a covariate
between treatment groups in the complete dataset and within the selected
bandwidth. The covariate can be binary (`typecov = "binary"`) or continuous
(`typecov = "conti"`):

```{r distplot}
rdo$distribution_plot(
  typerange   = "percentage",
  range_value = 25,
  num_it      = 100,
  covariate   = "sex",
  typecov     = "binary"
)
```

### Comparing several candidate bandwidths

The `summary_bandwidth()` method implements randomization-based tests with
multiplicity adjustment for assessing balance in the background variables
between treatment groups, for several candidate bandwidths at once. It returns
a table of adjusted p-values by covariate and bandwidth; large p-values
indicate subpopulations where the covariates are well balanced:

```{r summarybw}
rdo$summary_bandwidth(buffers = c(500, 1000, 1500), num_it = 200)
```

In practice we recommend a larger number of iterations (e.g.
`num_it = 1000` or more) for the final analysis; a smaller value is used here
to keep the vignette light.

## Analysis phase: inference on causal effects

The `causal_effect()` method is the main function of the package. Four modes
of inference are implemented through the `method` argument:

* `'Sharp FEP'`: Fisher's exact p-value approach for sharp RD designs within
  the selected subpopulations.
* `'Sharp Neyman'`: Neyman approach for sharp RD designs.
* `'Fuzzy FEP'`: Fisher's exact p-value approach for fuzzy RD designs.
* `'Fuzzy Neyman'`: Neyman approach for fuzzy RD designs.

In all cases, the user selects the bandwidths (`buffers`), the outcome and its
type (`"binary"` or `"numeric"`), and the number of iterations used to
approximate the randomization distribution.

### Sharp FEP

Under the sharp interpretation, we test the sharp null hypothesis of no
treatment effect for the eligibility status. The method reports, for each
bandwidth, the observed difference in average outcomes by assignment status
and the Fisher exact p-value, together with a histogram of the randomization
distribution of the test statistic (the dashed line marks the observed value):

```{r sharpfep}
rdo$causal_effect(
  method      = "Sharp FEP",
  buffers     = c(500, 1000, 1500),
  num_it      = 100,
  outcome     = "dropout",
  typeoutcome = "binary",
  plot        = TRUE
)
```

### Sharp Neyman

The Neyman approach estimates the average causal effect of eligibility with
its standard error and a confidence interval at the level defined by `cin`
(the alpha level, 0.05 by default):

```{r sharpneyman}
rdo$causal_effect(
  method      = "Sharp Neyman",
  buffers     = c(500, 1000, 1500),
  num_it      = 100,
  outcome     = "dropout",
  typeoutcome = "binary",
  cin         = 0.05,
  plot        = TRUE
)
```

### Fuzzy Neyman

In the fuzzy design, the treatment received (`W`, provided through the
`treatm_cov` argument) does not coincide with the assignment. The Neyman
approach reports both the intention-to-treat effect and the complier average
causal effect (CACE):

```{r fuzzyneyman}
rdo$causal_effect(
  method      = "Fuzzy Neyman",
  buffers     = c(500, 1000, 1500),
  num_it      = 100,
  outcome     = "dropout",
  typeoutcome = "binary",
  treatm_cov  = "W",
  plot        = TRUE
)
```

### Fuzzy FEP

The Fuzzy FEP approach tests the null hypothesis of no effect for compliers.
Noncompliance can be one-sided (`sided = "onesided"`) or two-sided
(`sided = "twosided"`). Three test statistics are used: the IV estimate, the
maximum likelihood estimate (MLE), and the posterior median of the CACE. The
`num_it_fuzzy` argument controls the number of iterations used to compute the
MLE/posterior mode of the complier average causal effects:

```{r fuzzyfep}
rdo$causal_effect(
  method       = "Fuzzy FEP",
  buffers      = c(500, 1000, 1500),
  num_it       = 100,
  outcome      = "dropout",
  typeoutcome  = "binary",
  sided        = "twosided",
  treatm_cov   = "W",
  num_it_fuzzy = 5,
  plot         = TRUE
)
```

Note that the Fuzzy FEP approach is computationally more demanding than the
other three; for final analyses with a large number of iterations, expect
longer running times.

## The Shiny application

All the functionality described above is also available through a
user-friendly Shiny application. It can be launched with:

```{r shiny, eval = FALSE}
open_LRErdd_framework()
```

The dashboard presents two sections: the input options on the left panel,
managed through a drop-down list covering all the steps of the workflow, and
the results on the right, in the result window.

![Workflow of the LRErdd Shiny application](Squeme.jpg){width=100%}

The steps mirror the programmatic workflow:

1. **Load data.** The user can choose the `grants` dataset included in the
   package, or upload a dataset from an Excel (`.xlsx`) or R (`.RData`) file.
2. **Define settings.** The forcing variable, the threshold, and whether the
   treatment group is below or above the threshold.
3. **Summary statistics.** Means of the selected variables by treatment
   assignment status.
4. **Bandwidth selection.** Interactive selection of the bandwidth (as a
   percentage of the range, symmetric, or asymmetric), with balance tables and
   plots updated dynamically.
5. **Summary bandwidth selection.** Randomization-based balance tests with
   multiplicity adjustment for several candidate bandwidths.
6. **Inference on causal effects.** The four modes of inference (Sharp FEP,
   Sharp Neyman, Fuzzy FEP, Fuzzy Neyman) with their specific settings.

## References

Li, F., Mattei, A. and Mealli, F. (2015). Bayesian inference for regression
discontinuity designs with application to the evaluation of Italian university
grants. *The Annals of Applied Statistics*, 9(4), 1906–1931.
[doi:10.1214/15-AOAS809](https://doi.org/10.1214/15-AOAS809)

## Session info

```{r session}
sessionInfo()
```
