---
title: "CSSS/POLS 512"
subtitle: "Lab 5: Panel Data — Dynamics, FE/RE, Mundlak, IRF"
author: "Ramses Llobet"
date: "Spring 2026"
output:
  xaringan::moon_reader:
    css: [default, metropolis, metropolis-fonts]
    lib_dir: libs
    nature:
      highlightStyle: github
      highlightLines: true
      countIncrementalSlides: false
      ratio: "16:9"
editor_options:
  chunk_output_type: console
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, fig.align = "center",
                      fig.width = 12, fig.height = 5.5,
                      warning = FALSE, message = FALSE,
                      dev = "svg", fig.retina = 2)

library(tidyverse)
library(plm)
library(fixest)
library(nlme)
library(parameters)
library(sandwich)
library(lmtest)
library(MASS)
library(simcf)
library(ggdag); library(dagitty)
library(patchwork)
library(broom)
library(scales)

lag <- dplyr::lag; filter <- dplyr::filter; select <- dplyr::select
set.seed(512)
```

# Today's Plan

.pull-left[
**Part 1: Theory + Data**
- DAG: `reg`, `edt` (moderator), `oil`
- The Przeworski 1950–1990 panel
- Within-vs-between framing

**Part 2: Dynamics workflow**
- ACF/PACF on detrended series
- Per-country ADF/PP scan
- Panel unit-root **constellation** (CD, MW/IPS, Hadri, CIPS)
- Verdict: I(1)-like; choose Path A
]

.pull-right[
**Part 3: Panel models family**
- Pooled / FE / TWFE / RE / Mundlak (REWB)
- Static vs dynamic (AR(1), ARDL(1,1))
- corARMA(1) for RE / Mundlak
- Hausman, PCSE, Driscoll–Kraay

**Part 4: Counterfactual via IRF + LRE**
- FE-ARDL(1,1) closed form
- Permanent democratization
- Long-run effect by **education**
]

---
class: inverse, center, middle

# Part 1 — Theory and Data

---

# A Toy Theory of Politics in Panel Data

We study **regime → growth** with three covariate roles:

.pull-left[
1. **Within-rich treatment**: `reg` (1 = democracy; flips on coups, pacts, transitions)
2. **Slow-moving covariate AND moderator**: `edt` (cumulative education) — moderates the regime-growth slope
3. **Time-invariant control**: `oil` (major oil exporter, 1/0)

**Outcome**: $\ln$(GDP per worker)

**Hypothesis**: more-educated workforces benefit more (or less) from democratization.
]

.pull-right[
```{r p1-dag, echo=FALSE, out.width="100%"}
knitr::include_graphics("output/panel_dag.png")
```
]

---

# Within vs Between — Which $\beta$ Are You Estimating?

| Specification | What $\hat\beta$ identifies | Identifying assumption |
|:---|:---|:---|
| **Pooled OLS** | mixture of within + between | $u_{it}\perp X_{it}$; $\alpha_i$ common |
| **Fixed effects (within)** | within only ($\beta_W$) | $\varepsilon_{it}\perp x_{it}$ given $\alpha_i$; allows $\text{Cov}(\alpha_i, X)\neq 0$ |
| **Random effects** | matrix-weighted average | $\alpha_i\perp X_i$ |
| **Mundlak / REWB** | $\beta_W$ and $\beta_B$ separately | RE on residuals; $\bar x_i$ absorbs cross-level confounding |

--

**Decision logic**:

- *"Does democratization, **for a given country**, raise GDP?"* → $\beta_W$
- *"Are democracies, **on average across countries**, richer?"* → $\beta_B$
- *"Both — and do they differ?"* → Mundlak / REWB returns both, $\beta_W = \beta_B$ is testable

.footnote[*Bell & Jones (2015), Kropko & Kubinec (2020).*]

---

# The Przeworski Democracy Panel

```{r p1-load-democracy, include=FALSE, cache=TRUE}
democracy <- read_csv("data/democracy.csv", show_col_types = FALSE) |>
  rename_with(tolower) |>
  mutate(ln_gdpw   = log(gdpw),
         country_f = factor(country),
         year_f    = factor(year))
```

.pull-left[
**Dimensions**: $N = 135$ countries, 1950–1990, **unbalanced** ($T_i \in [10, 40]$).

**Variables**: `ln_gdpw`, `reg`, `edt`, `oil`, `region`.

`pvar()` confirms `oil` is between-only; `reg` and `edt` vary both ways.

**Spaghetti plot →** trends, drift, country-specific slopes — coloured by region.
]

.pull-right[
```{r p1-spaghetti-region, fig.width=6, fig.height=4.8}
ggplot(democracy, aes(year, ln_gdpw, group = country, colour = region)) +
  geom_line(alpha = 0.5) +
  scale_colour_brewer(palette = "Dark2") +
  labs(x = NULL, y = "log GDP per worker", colour = NULL) +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom",
        legend.text = element_text(size = 9))
```
]

---

# Unbalanced Panel: $T_i$ Distribution

```{r p1-T-hist, fig.width=10, fig.height=4.5}
panel_T <- democracy |>
  group_by(country, ctyname, region) |>
  summarise(T_i = sum(!is.na(ln_gdpw)), .groups = "drop")

ggplot(panel_T, aes(T_i, fill = region)) +
  geom_histogram(binwidth = 2, alpha = 0.85, boundary = 0) +
  scale_fill_brewer(palette = "Dark2") +
  labs(x = "Usable observations per country",
       y = "# countries", fill = NULL) +
  theme_minimal(base_size = 13) +
  theme(legend.position = "bottom")
```

Most countries have $T_i \approx 30$–40; African and Asian post-colonial states cluster at the lower end. Short $T$ matters for unit-root power and Nickell bias.

---
class: inverse, center, middle

# Part 2 — Dynamics Workflow

---

# Why Test for Stationarity Before Estimating?

A near-unit-root outcome creates two problems:

1. **Spurious regression** — coefficients can look significant even when there is no real relationship.
2. **AR(1) on level becomes a signature**: $\hat\phi$ on `ln_gdpw_lag` lands near 1 → the long-run multiplier $\hat\beta/(1-\hat\phi)$ blows up.

Workflow (per Lab 5):

1. **Visualize** all series — spaghetti by region.
2. **Detrend** country-by-country (OLS); inspect ACF/PACF on residuals.
3. **Per-series ADF + PP** → histogram of unit-level $p$-values.
4. **Panel unit-root tests**: read a *constellation*, not a single verdict.
5. **Pick a path**: levels with ARDL(1) (Path A) or first differences (Path B).

---

# Per-Series Unit-Root Scan

After removing each country's linear trend, run ADF and PP on the residuals; plot the distribution of $p$-values.

```{r p2-unit-root-hist, fig.width=10, fig.height=4.5, cache=TRUE}
library(tseries)
countries_all <- sort(unique(democracy$ctyname))
unit_root_tests <- tibble()
for (c0 in countries_all) {
  df_c <- democracy |> filter(ctyname == c0) |> arrange(year)
  if (sum(!is.na(df_c$ln_gdpw)) < 10) next
  trend_fit <- lm(ln_gdpw ~ year, data = df_c, na.action = na.exclude)
  y <- na.omit(residuals(trend_fit))
  if (length(y) < 8) next
  unit_root_tests <- bind_rows(
    unit_root_tests,
    tibble(ctyname = c0,
           adf = adf.test(y)$p.value,
           pp  = pp.test(y)$p.value)
  )
}
unit_root_tests |>
  pivot_longer(c(adf, pp), names_to = "test", values_to = "p") |>
  ggplot(aes(p, fill = test)) +
  geom_histogram(bins = 25, alpha = 0.7, position = "identity") +
  geom_vline(xintercept = 0.05, linetype = "dashed") +
  facet_wrap(~ test, ncol = 2,
             labeller = labeller(test = c(adf = "ADF", pp = "Phillips–Perron"))) +
  scale_fill_manual(values = c(adf = "#1b9e77", pp = "#d95f02")) +
  labs(x = "p-value", y = "# countries") +
  theme_minimal(base_size = 13) +
  theme(legend.position = "none")
```

Most countries land $p > 0.05$: low power at $T \le 30$ does not let us reject the unit-root null country-by-country.

---

# Panel Unit-Root Constellation

We read **multiple tests jointly** because no single one is decisive at this $T$.

| Step | Test | $H_0$ | Reading |
|:----|:----|:----|:----|
| (a) | **Pesaran CD** | cross-sectional independence | If rejected → 1st-gen tests biased |
| (b) | **Maddala-Wu/Fisher**, **IPS** | unit root in *all* panels | 1st-gen, assume CSI |
| (c) | **Hadri** | stationarity in *all* panels | KPSS-flip; over-rejects under CSD (Hlouskova & Wagner 2006) |
| (d) | **Pesaran CIPS** | unit root, common-factor corrected | 2nd-gen, robust to CSD |

--

**Verdict for `ln_gdpw`**: CSD present (a). Fisher rejects but IPS does not (b) — Fisher is sensitive to a few low-$p$ countries. Hadri rejects but discount under CSD. **CIPS does not reject**. → **strong persistence consistent with I(1)-type behavior**.

---

# Two Paths — We Pick Path A

| Path | Outcome | Dynamics absorbed by | Trade-off |
|:--:|:--|:--|:--|
| **A** | $\ln$-level | Lagged DV in levels (ARDL(1)) | Coefficients are level effects; Beck & Katz (2011) recommend; **Nickell bias** for short $T$ |
| **B** | $\Delta\ln$ | Lagged differences | Outcome is a growth rate; Mundlak split is awkward; forecasts un-differenced |

--

**One important exception** — pooled OLS with AR(1) on the level shows $\hat\phi \approx 0.99$ (the I(1) signature). For the pooled model only, we use **Path B (FD + ARDL(1,1))**: outcome $\Delta y$, lagged $\Delta y$, and lagged regressors. The growth-rate equation has a well-behaved $\hat\phi$.

For FE / TWFE / RE / Mundlak, we stay on Path A.

---
class: inverse, center, middle

# Part 3 — Estimating Panel Models

---

# One Equation, Five Estimators

$$
y_{it} \;=\; \alpha + \beta_1\,\text{reg}_{it} + \beta_2\,\text{edt}_{it} + \beta_3\,(\text{reg}_{it}\!\cdot\!\text{edt}_{it}) + \beta_4\,\text{oil}_i + u_{it}
$$

| Subsection | Static | AR(1) (lagged DV) | ARDL(1,1) (+ lagged `reg`, `edt`) | corARMA(1) |
|:---|:---:|:---:|:---:|:---:|
| Pooled OLS | ✓ | ✓ | ✓ | — |
| FE (within) | ✓ | ✓ | ✓ | — |
| TWFE | ✓ | ✓ | ✓ | — |
| RE | ✓ | — | — | ✓ |
| Mundlak / REWB | ✓ | — | — | ✓ |

--

**Why no LDV in RE / Mundlak?** RE-LDV faces the Wooldridge (2005) initial-conditions problem; Mundlak-LDV breaks the within-between decomposition. corARMA absorbs persistence in the residuals.

---

# Fitting the Family

```{r p3-fits, include=FALSE, cache=TRUE}
democracy_dyn <- democracy |>
  group_by(country) |>
  arrange(year) |>
  mutate(ln_gdpw_lag   = lag(ln_gdpw),
         reg_lag       = lag(reg),
         edt_lag       = lag(edt),
         d_ln_gdpw     = ln_gdpw - ln_gdpw_lag,
         d_ln_gdpw_lag = lag(d_ln_gdpw)) |>
  ungroup()

db_pool <- democracy_dyn |>
  drop_na(ln_gdpw, ln_gdpw_lag, d_ln_gdpw, d_ln_gdpw_lag,
          reg, reg_lag, edt, edt_lag, oil)

# Pooled (best: FD ARDL(1,1))
fit_pool          <- lm(ln_gdpw  ~ reg * edt + oil, data = db_pool)
fit_pool_fd_ardl11 <- lm(d_ln_gdpw ~ d_ln_gdpw_lag +
                                     reg + reg_lag + edt + edt_lag +
                                     reg:edt + reg_lag:edt_lag + oil,
                         data = db_pool)

# FE
fit_fe       <- feols(ln_gdpw ~ reg * edt + oil | country,
                      data = democracy, cluster = ~ country)
fit_fe_ardl11 <- feols(
  ln_gdpw ~ ln_gdpw_lag + reg + reg_lag + edt + edt_lag +
            reg:edt + reg_lag:edt_lag + oil | country,
  data = democracy_dyn, cluster = ~ country
)

# TWFE
fit_twfe       <- feols(ln_gdpw ~ reg * edt + oil | country + year,
                        data = democracy, cluster = ~ country)
fit_twfe_ardl11 <- feols(
  ln_gdpw ~ ln_gdpw_lag + reg + reg_lag + edt + edt_lag +
            reg:edt + reg_lag:edt_lag + oil | country + year,
  data = democracy_dyn, cluster = ~ country
)

# RE — static and corARMA(1) only
fit_re <- lme(
  fixed     = ln_gdpw ~ reg * edt + oil,
  random    = ~ 1 | country,
  data      = democracy, na.action = na.omit, method = "REML"
)
fit_re_corar <- lme(
  fixed       = ln_gdpw ~ reg * edt + oil,
  random      = ~ 1 | country,
  correlation = corARMA(form = ~ year | country, p = 1, q = 0),
  data        = democracy, na.action = na.omit, method = "REML"
)

# Mundlak / REWB — split reg, edt, and reg*edt into within / between
mund <- democracy |>
  drop_na(ln_gdpw, reg, edt, oil) |>
  mutate(reg_x_edt = reg * edt) |>
  parameters::demean(select = c("reg", "edt", "reg_x_edt"),
                     by = "country", verbose = FALSE)

fit_mundlak <- lme(
  fixed     = ln_gdpw ~ reg_within + reg_between +
                       edt_within + edt_between +
                       reg_x_edt_within + reg_x_edt_between + oil,
  random    = ~ 1 | country,
  data      = mund, na.action = na.omit, method = "REML"
)
fit_mundlak_corar <- lme(
  fixed       = ln_gdpw ~ reg_within + reg_between +
                         edt_within + edt_between +
                         reg_x_edt_within + reg_x_edt_between + oil,
  random      = ~ 1 | country,
  correlation = corARMA(form = ~ year | country, p = 1, q = 0),
  data        = mund, na.action = na.omit, method = "REML"
)

# plm versions for Hausman + panel SEs
fit_fe_plm <- plm(ln_gdpw ~ reg * edt + oil,
                  data = democracy, index = c("country_f", "year_f"),
                  model = "within")
fit_re_plm <- plm(ln_gdpw ~ reg * edt + oil,
                  data = democracy, index = c("country_f", "year_f"),
                  model = "random")
```

**Pooled OLS**: level AR(1) shows the I(1) signature ($\hat\phi \approx 0.99$) → switch outcome to first differences. Pick **FD + ARDL(1,1)**.

**FE / TWFE**: stay in levels with **ARDL(1,1)** (lagged DV + lagged `reg` + lagged `edt` + lagged interaction).

**RE**: **corARMA(1)** — AR(1) on residuals; no LDV (Wooldridge initial conditions).

**Mundlak / REWB**: **corARMA(1)** + within/between split on `reg`, `edt`, and `reg × edt` (precomputed product).

---

# Pooled OLS — Where the Headline Lives

```{r p3-pool-print}
broom::tidy(fit_pool) |>
  mutate(across(estimate:p.value, ~ round(.x, 3))) |>
  knitr::kable(format = "html")
```

- $\hat\beta$ on `reg` and `reg × edt` is **identified mostly off cross-country variation** — more-educated countries differ from less-educated countries in their average regime-growth slope.
- Pooled OLS in levels is also the spec where the I(1) signature appears: AR(1) on the level gives $\hat\phi \approx 0.99$. Differencing the outcome restores stationarity (FD + ARDL(1,1) chosen for §2.8).

---

# Fixed Effects — Does the Moderation Survive Within?

```{r p3-fe-print}
ct <- coeftest(fit_fe_plm, vcov. = vcovHC(fit_fe_plm, method = "arellano"))
as.data.frame(unclass(ct)) |>
  rownames_to_column("term") |>
  rename(estimate = Estimate, std.error = `Std. Error`,
         statistic = `t value`, p.value = `Pr(>|t|)`) |>
  mutate(across(estimate:p.value, ~ round(.x, 4))) |>
  knitr::kable(format = "html")
```

--

- `oil` is absorbed (time-invariant).
- The within `reg × edt` interaction tells us whether the moderation is a *within-country* phenomenon: *as a country's education rises over time, does the regime effect change?*
- If the FE interaction is small while pooled OLS's was large → between-country variation was doing the talking. → **Same data, different stories under different identifying assumptions.**

---

# Mundlak / REWB — The Diagnostic

```{r p3-mundlak-print}
summary(fit_mundlak_corar)$tTable |>
  as.data.frame() |>
  rownames_to_column("term") |>
  filter(term %in% c("reg_within", "reg_between",
                     "edt_within", "edt_between",
                     "reg_x_edt_within", "reg_x_edt_between", "oil")) |>
  mutate(across(c(Value, Std.Error, `t-value`, `p-value`), ~ round(.x, 3))) |>
  knitr::kable(format = "html")
```

--

- `reg_within` / `reg_between` — within-country regime effect vs cross-country slope.
- `reg_x_edt_within` / `reg_x_edt_between` — does the moderation by education operate *within* (rising education within a country changes the regime effect) or *between* (more-educated countries have a different regime-growth slope)?
- `oil` retains its main effect (RE flexibility, FE shortcoming).

**This is exactly the diagnostic Hausman gives, with covariate-by-covariate detail.**

---

# Hausman Test

$$
H = (\hat\beta_{FE} - \hat\beta_{RE})^\top [V_{FE} - V_{RE}]^{-1} (\hat\beta_{FE} - \hat\beta_{RE}) \;\sim\; \chi^2_k
$$

- $H_0$: $\text{Cov}(\alpha_i, X_{it}) = 0$ — RE consistent and efficient.
- $H_1$: RE inconsistent; only FE consistent.
- The variance of the difference collapses to $V_{FE} - V_{RE}$ because RE is *efficient* under $H_0$ (Hausman 1978).

```{r p3-hausman-print}
ht <- phtest(fit_fe_plm, fit_re_plm)
sprintf("chisq = %.2f,  df = %d,  p = %.4f",
        as.numeric(ht$statistic), as.numeric(ht$parameter),
        as.numeric(ht$p.value))
```

--

**Bell & Jones (2015) caveat**: do not use Hausman as a model-selection switch. Even when it rejects, REWB is often the better choice — it returns *both* within and between estimates so you can report the relevant comparison.

---

# Panel Standard Errors

| SE | Allows | When |
|:---|:---|:---|
| **Cluster-robust by unit** | Within-country correlation | Many clusters; residuals roughly independent across countries |
| **PCSE (Beck & Katz 1995)** | Contemporaneous *cross-sectional* dependence | TSCS panels — common shocks hit many countries the same year |
| **Driscoll–Kraay (1998)** | Cross-sectional **+** serial correlation | Moderate-to-large $T$; safest default |

```{r p3-se-print}
ses <- list(
  cluster  = vcovHC(fit_fe_plm, method = "arellano"),
  pcse     = vcovBK(fit_fe_plm),
  driscoll = vcovSCC(fit_fe_plm)
)
target  <- c("reg", "edt", "reg:edt")
ses_tab <- map(ses, function(V) coeftest(fit_fe_plm, vcov. = V)[target, 2])
bind_cols(coefficient = target, as_tibble(ses_tab)) |>
  knitr::kable(format = "html", digits = 4)
```

PCSE is the TSCS default; Driscoll–Kraay is the safer choice when residual autocorrelation persists after the lagged DV.

---
class: inverse, center, middle

# Part 4 — Counterfactual via IRF and LRE

---

# The Forecast Question

> *If a country democratized **permanently**, what would the trajectory of $\ln$ GDP per worker look like over the next 20 years — and how does it depend on the workforce's education level?*

--

We use the **FE-ARDL(1,1)** model: country fixed effects + lagged DV + contemporaneous and lagged `reg`, `edt`, and `reg × edt`.

The output is the **impulse response function (IRF)** — cumulative effect at horizon $h$ — and its asymptote, the **long-run equilibrium effect (LRE)**.

This is the panel analog of Lab 4's IRF, with the moderation by education made explicit.

---

# Closed-Form IRF

For the dynamic FE-ARDL(1,1) model under permanent democratization at $t = 0$, with `edt` held at level $e$:

$$
\mathrm{IRF}(h \mid e)
\;=\;
A(e) \cdot \frac{1 - \phi^{h+1}}{1 - \phi}
\;+\;
B(e) \cdot \frac{1 - \phi^{h}}{1 - \phi}
$$

where

- $A(e) = \beta_0 + \gamma_0\,e$ is the **impact** effect (year of democratization).
- $B(e) = \beta_1 + \gamma_1\,e$ is the **delayed transmission** through `reg_lag` and `reg_lag × edt_lag`.

--

**Long-run equilibrium effect** (asymptote as $h \to \infty$, $|\phi| < 1$):

$$
\mathrm{LRE}(e) \;=\; \frac{A(e) + B(e)}{1 - \phi} \;=\; \frac{\beta_0 + \beta_1 + (\gamma_0 + \gamma_1)\,e}{1 - \phi}
$$

Parametric simulation (King–Tomz–Wittenberg): draw $S = 1{,}000$ coefficient vectors from MVN, evaluate IRF at each draw and horizon, take quantile bands.

---

# IRF: Permanent Democratization at Two Education Levels

```{r p4-irf, include=FALSE, cache=TRUE}
irf_path <- function(e, phi, beta0, beta1, gamma0, gamma1, H = 20) {
  A <- beta0 + gamma0 * e
  B <- beta1 + gamma1 * e
  h_seq         <- 0:H
  geom_h_plus_1 <- (1 - phi^(h_seq + 1)) / (1 - phi)
  geom_h        <- ifelse(h_seq == 0, 0, (1 - phi^h_seq) / (1 - phi))
  A * geom_h_plus_1 + B * geom_h
}

edt_lo <- as.numeric(quantile(democracy$edt, 0.25, na.rm = TRUE))
edt_hi <- as.numeric(quantile(democracy$edt, 0.75, na.rm = TRUE))

set.seed(2025)
S       <- 1000
H_irf   <- 20
draws_ardl <- mvrnorm(n = S,
                      mu    = coef(fit_fe_ardl11),
                      Sigma = vcov(fit_fe_ardl11))

irf_lo <- matrix(NA_real_, S, H_irf + 1)
irf_hi <- matrix(NA_real_, S, H_irf + 1)
for (s in seq_len(S)) {
  d <- draws_ardl[s, ]
  irf_lo[s, ] <- irf_path(edt_lo, d["ln_gdpw_lag"],
                          d["reg"], d["reg_lag"],
                          d["reg:edt"], d["reg_lag:edt_lag"], H = H_irf)
  irf_hi[s, ] <- irf_path(edt_hi, d["ln_gdpw_lag"],
                          d["reg"], d["reg_lag"],
                          d["reg:edt"], d["reg_lag:edt_lag"], H = H_irf)
}
irf_band <- bind_rows(
  tibble(h = 0:H_irf,
         pe = colMeans(irf_lo),
         lo = apply(irf_lo, 2, quantile, 0.025),
         hi = apply(irf_lo, 2, quantile, 0.975),
         scenario = sprintf("Low education (edt = %.2f)", edt_lo)),
  tibble(h = 0:H_irf,
         pe = colMeans(irf_hi),
         lo = apply(irf_hi, 2, quantile, 0.025),
         hi = apply(irf_hi, 2, quantile, 0.975),
         scenario = sprintf("High education (edt = %.2f)", edt_hi))
)
```

```{r p4-irf-plot, fig.width=11, fig.height=5}
ggplot(irf_band, aes(h, pe, colour = scenario, fill = scenario)) +
  geom_ribbon(aes(ymin = lo, ymax = hi), alpha = 0.22, colour = NA) +
  geom_line(linewidth = 0.85) +
  geom_hline(yintercept = 0, linetype = "dashed", colour = "grey45") +
  labs(x = "Horizon h (years after democratization)",
       y = "Cumulative effect on log GDP per worker",
       colour = NULL, fill = NULL) +
  theme_minimal(base_size = 14) +
  theme(legend.position = "bottom")
```

---

# Long-Run Equilibrium Effect (LRE)

```{r p4-lre, fig.width=10}
lre_lo_draws <- (draws_ardl[, "reg"] + draws_ardl[, "reg_lag"] +
                 (draws_ardl[, "reg:edt"] + draws_ardl[, "reg_lag:edt_lag"]) * edt_lo) /
                (1 - draws_ardl[, "ln_gdpw_lag"])
lre_hi_draws <- (draws_ardl[, "reg"] + draws_ardl[, "reg_lag"] +
                 (draws_ardl[, "reg:edt"] + draws_ardl[, "reg_lag:edt_lag"]) * edt_hi) /
                (1 - draws_ardl[, "ln_gdpw_lag"])

tibble(
  scenario = c(sprintf("Low education (edt = %.2f, P25)",  edt_lo),
               sprintf("High education (edt = %.2f, P75)", edt_hi)),
  pe = c(mean(lre_lo_draws),            mean(lre_hi_draws)),
  lo = c(quantile(lre_lo_draws, 0.025), quantile(lre_hi_draws, 0.025)),
  hi = c(quantile(lre_lo_draws, 0.975), quantile(lre_hi_draws, 0.975))
) |>
  knitr::kable(format = "html", digits = 3,
               caption = "LRE: long-run effect of permanent democratization, FE-ARDL(1,1).")
```

--

**How to read it.** A larger LRE for the high-`edt` scenario says democratization's long-run growth payoff rises with the workforce's education — a within-country moderation by human capital. Wide CIs reflect the Nickell-bias caveat: at $\hat\phi$ close to 1, the LRE is sensitive to small changes in $\hat\phi$.

---
class: inverse, center, middle

# Wrap-Up

---

# What We Learned Today

1. **Within vs between is the substantive question**, not a methodological footnote. Mundlak / REWB returns both — Bell & Jones (2015): make it the default.

2. **Test before you estimate**. The panel unit-root *constellation* (CD + Fisher-MW + IPS + Hadri + CIPS) gave us a defensible I(1)-like verdict where no single test was decisive at $T \le 30$.

3. **Path A (ARDL) for FE / TWFE; Path B (FD) for pooled OLS**. The level-AR(1) $\hat\phi \approx 0.99$ in pooled is the I(1) signature.

4. **No LDV in RE / Mundlak**. corARMA(1) is the natural dynamic version — it absorbs persistence in the residuals without breaking the within-between split (REWB) or running into Wooldridge initial-conditions (RE).

5. **The IRF + LRE generalizes Lab 4's forecast to panels** — closed-form propagation, parametric simulation, moderator made visible at the horizon scale.

--

**Next week**: dynamic-panel GMM (Arellano–Bond, Arellano–Bover) to address the Nickell bias.

---

# References

- Beck, N., & Katz, J. N. (1995). What to do (and not to do) with TSCS data. *APSR*.
- Beck, N., & Katz, J. N. (2011). Modeling dynamics in TSCS political-economy data. *Annu. Rev. Polit. Sci.*
- Bell, A., & Jones, K. (2015). Explaining fixed effects: Random effects modeling of TSCS and panel data. *PSRM*.
- Driscoll, J. C., & Kraay, A. C. (1998). Consistent covariance matrix estimation with spatially dependent panel data. *RES*.
- Hadri, K. (2000). Testing for stationarity in heterogeneous panel data. *EJ*.
- Hlouskova, J., & Wagner, M. (2006). The performance of panel unit root and stationarity tests. *Econ. Rev.*
- Im, K. S., Pesaran, M. H., & Shin, Y. (2003). Testing for unit roots in heterogeneous panels. *J. Econometrics*.
- King, G., Tomz, M., & Wittenberg, J. (2000). Making the most of statistical analyses. *AJPS*.
- Kropko, J., & Kubinec, R. (2020). Interpretation and identification of within-unit and cross-sectional variation. *PLOS ONE*.
- Maddala, G. S., & Wu, S. (1999). A comparative study of unit root tests with panel data. *OBES*.
- Mundlak, Y. (1978). On the pooling of time series and cross section data. *Econometrica*.
- Nickell, S. (1981). Biases in dynamic models with fixed effects. *Econometrica*.
- Pesaran, M. H. (2007). A simple panel unit root test in the presence of cross-section dependence. *J. Appl. Econ.*

---
class: inverse, center, middle

# Questions?

`rllobet@uw.edu`
