Skip to contents

A convenience generator that mirrors the data-generating processes used in the rdpartial documentation and unit tests. The function produces a data frame ready for bounds_sharp(), bounds_fuzzy(), and bootstrap_bounds(), while also returning the true treatment effect at the cutoff for quick sanity checks.

Usage

simulate_rdd_data(
  n = 4000,
  cutoff = 16,
  dist = c("poisson", "uniform"),
  lambda = 15,
  range = c(8L, 25L),
  beta = c(0, 0.1, 0.002),
  tau = 1,
  sigma = 1,
  design = c("fuzzy", "sharp"),
  p0 = 0.2,
  p1 = 0.8,
  manip_width = 0,
  manip_prob = 0,
  seed = NULL
)

Arguments

n

Integer sample size (≥ 1).

cutoff

Numeric threshold. Must be integer-aligned with the support of x.

dist

Either "poisson" (default) or "uniform".

lambda

Poisson mean when dist = "poisson".

range

Integer length-2 support when dist = "uniform".

beta

Numeric length-3 vector for the quadratic mean of Y(0).

tau

Constant treatment effect added to Y(1) (default 1).

sigma

Error SD for both potential outcomes (default 1).

design

"fuzzy" (default) or "sharp".

p0, p1

Treatment probabilities below / above cutoff when design = "fuzzy".

manip_width

Numeric ≥ 0 - interval width subject to manipulation just below the cutoff.

manip_prob

Probability of manipulation for units in that interval (default 0).

seed

Optional integer for reproducibility.

Value

A data.frame with columns:

  • x - running variable after manipulation.

  • y - realised outcome.

  • z - treatment status.

  • x_orig - running variable before manipulation.

  • manipulated - logical flag.

The object carries attributes:

  • ate_cutoff - true treatment effect at the cutoff (tau).

  • call - original function call.

Outline of the DGP

  1. Draw an integer running variable x from either a Poisson or discrete uniform distribution.

  2. (Optional) Manipulate units with x in (cutoff − manip_width, cutoff) above the threshold with probability manip_prob.

  3. Generate potential outcomes Y(0) and Y(1) as quadratic functions of x plus Normal noise.

  4. Assign treatment either sharply (z = 1(x >= cutoff)) or fuzzily via Bernoulli probabilities p0, p1 below / above the cutoff.

  5. Observe realised outcome y = Y(z).

Examples

set.seed(42)
sim <- simulate_rdd_data(n = 2000, cutoff = 16, design = "fuzzy",
                         manip_width = 0.4, manip_prob = 0.25)
head(sim)
#>    x         y z x_orig manipulated
#> 1 20 4.1729792 1     20       FALSE
#> 2 12 1.2726848 0     12       FALSE
#> 3 15 3.1496858 0     15       FALSE
#> 4 10 0.6554904 0     10       FALSE
#> 5 14 1.9406387 0     14       FALSE
#> 6 20 2.6233708 1     20       FALSE
#> 
#> True ATE at cutoff: 1 
attr(sim, "ate_cutoff")
#> [1] 1