Nothing
## ----setup, include = FALSE---------------------------------------------------
knitr::opts_chunk$set(
collapse = TRUE, comment = "#>",
fig.width = 7, fig.height = 4, warning = FALSE, message = FALSE
)
library(NonlinearDiD)
library(ggplot2)
set.seed(101)
## ----demo_scale---------------------------------------------------------------
# Demonstrate scale sensitivity
p_ctrl_pre <- 0.30; p_ctrl_post <- 0.40
p_treat_pre <- 0.25; p_treat_post <- 0.35
cat("=== Probability Scale ===\n")
cat("Control change: ", round(p_ctrl_post - p_ctrl_pre, 4), "\n")
cat("Treated change: ", round(p_treat_post - p_treat_pre, 4), "\n")
cat("DiD (prob): ", round((p_treat_post - p_treat_pre) - (p_ctrl_post - p_ctrl_pre), 4), "\n\n")
cat("=== Log-Odds (Logit) Scale ===\n")
cat("Control change: ", round(qlogis(p_ctrl_post) - qlogis(p_ctrl_pre), 4), "\n")
cat("Treated change: ", round(qlogis(p_treat_post) - qlogis(p_treat_pre), 4), "\n")
cat("DiD (logit): ", round((qlogis(p_treat_post) - qlogis(p_treat_pre)) -
(qlogis(p_ctrl_post) - qlogis(p_ctrl_pre)), 4), "\n\n")
cat("=== Probit Scale ===\n")
cat("Control change: ", round(qnorm(p_ctrl_post) - qnorm(p_ctrl_pre), 4), "\n")
cat("Treated change: ", round(qnorm(p_treat_post) - qnorm(p_treat_pre), 4), "\n")
cat("DiD (probit): ", round((qnorm(p_treat_post) - qnorm(p_treat_pre)) -
(qnorm(p_ctrl_post) - qnorm(p_ctrl_pre)), 4), "\n")
## ----severity-----------------------------------------------------------------
# Show severity across baseline probability values
baseline_probs <- seq(0.05, 0.45, by = 0.05)
delta_p <- 0.10 # same additive change for both groups
severity_df <- do.call(rbind, lapply(baseline_probs, function(p0) {
p1 <- p0 + delta_p
# Parallel in prob => same change
# Logit DiD if treated has different baseline (p0 - 0.05)
p0_treat <- max(p0 - 0.05, 0.02)
p1_treat <- p0_treat + delta_p
logit_did <- (qlogis(p1_treat) - qlogis(p0_treat)) -
(qlogis(p1) - qlogis(p0))
data.frame(
baseline_ctrl = p0,
baseline_treat = p0_treat,
logit_did = logit_did
)
}))
cat("Logit-scale DiD when true probability DiD = 0:\n")
print(severity_df, digits = 3, row.names = FALSE)
cat("\nLarger deviations at low baseline probabilities.\n")
## ----simulation---------------------------------------------------------------
# DGP: parallel trends on logit scale
dat <- sim_binary_panel(
n = 1000,
nperiods = 8,
prop_treated = 0.5,
n_cohorts = 3,
true_att = c(0.20, 0.35, 0.25),
base_prob = 0.20, # low baseline: nonlinearity matters most
unit_fe_sd = 0.5,
seed = 42
)
cat("Baseline outcome rate (untreated, pre-period):",
round(mean(dat$y[dat$D == 0 & dat$period == 1]), 3), "\n")
cat("True ATTs (avg):", round(mean(c(0.20, 0.35, 0.25)), 3), "\n\n")
## ----fit_both-----------------------------------------------------------------
# Logit DiD
res_logit <- nonlinear_attgt(
dat, "y", "period", "id", "g",
outcome_model = "logit",
control_group = "nevertreated"
)
# Linear DiD
res_linear <- nonlinear_attgt(
dat, "y", "period", "id", "g",
outcome_model = "linear",
control_group = "nevertreated"
)
# Aggregate
agg_logit <- nonlinear_aggte(res_logit, type = "dynamic")
agg_linear <- nonlinear_aggte(res_linear, type = "dynamic")
cat("=== Overall ATT ===\n")
cat("Linear DiD: ", round(agg_linear$overall_att, 4), "\n")
cat("Logit DiD: ", round(agg_logit$overall_att, 4), "\n")
cat("True ATT: ", round(mean(c(0.20, 0.35, 0.25)), 4), "\n")
## ----pretrends_both-----------------------------------------------------------
# Test on logit scale
pt_logit <- nonlinear_pretest(res_logit, plot = FALSE)
cat("Pre-trends test (logit scale):\n")
cat(" Joint p-value:", round(pt_logit$joint_pval, 4), "\n\n")
# Test on linear scale
pt_linear <- nonlinear_pretest(res_linear, plot = FALSE)
cat("Pre-trends test (linear scale):\n")
cat(" Joint p-value:", round(pt_linear$joint_pval, 4), "\n\n")
cat("Note: If true DGP is logit-scale parallel trends, the linear-scale\n")
cat("pre-trends test may spuriously reject due to functional form.\n")
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.