In the lecture we interacted state ownership with civil liberties and read the result as "the state-ownership slope at different levels of civil liberties". But an interaction is symmetric — the very same term also tells us how the civil-liberties slope changes with state ownership. Here you read it from that other side, and then decide whether the pattern is real.

  1. Rebuild the Lecture 9 / 11 triangle. (Same pipeline: V-Dem, the World Bank $3.00 poverty line, a cached fallback, and both predictors mean-centred.)
pacman::p_load(tidyverse, estimatr, vdemdata, wbstats, modelsummary)

Dat_vdem <- vdem %>%
  as_tibble() %>%
  select(country_text_id, year,
         civ_liberties = v2xcl_rol, state_own_raw = v2clstown) %>%
  mutate(state_ownership = -state_own_raw)

Dat_pov <- tryCatch(
  wb_data("SI.POV.DDAY", start_date = 1972, end_date = 2025),
  error = function(e) readRDS("data/wb_poverty_raw.rds")   # offline fallback
) %>%
  rename(poverty = SI.POV.DDAY, year = date, country_text_id = iso3c) %>%
  select(country_text_id, year, country, poverty) %>%
  drop_na(poverty) %>%
  group_by(country) %>% filter(year == max(year)) %>% ungroup()

Dat <- inner_join(Dat_pov, Dat_vdem, by = c("country_text_id", "year")) %>%
  drop_na(poverty, state_ownership, civ_liberties) %>%
  mutate(
    mc_state = state_ownership - mean(state_ownership),
    mc_civ   = civ_liberties  - mean(civ_liberties)
  )
  1. Fit the interaction — exactly the lecture model.
ols_int <- lm_robust(poverty ~ mc_state * mc_civ, data = Dat)

modelsummary(list("Poverty" = ols_int),
             coef_rename = c("mc_state" = "State ownership",
                             "mc_civ" = "Civil liberties",
                             "mc_state:mc_civ" = "State own. × Civ. lib."),
             stars = TRUE, gof_map = c("nobs", "r.squared"),
             output = "kableExtra")

The interaction coefficient is . In the lecture we read this as "how the state-ownership slope changes per unit of civil liberties". Because the interaction is symmetric, it also means:

  1. Read the civil-liberties slope at three levels of state ownership. The civil-liberties slope is b_civ + b_interaction × (state ownership). With mc_state centred, one standard deviation is about 1. Compute the slope at low, average and high state ownership:

    • Low state ownership (\(-1\) SD):
    • Average state ownership:
    • High state ownership (\(+1\) SD):
b    <- coef(ols_int)
sd_s <- sd(Dat$mc_state)

b["mc_civ"] + b["mc_state:mc_civ"] * (-sd_s) # low state ownership
b["mc_civ"]                                  # average
b["mc_civ"] + b["mc_state:mc_civ"] * ( sd_s) # high state ownership
  1. Draw the predicted lines — civil liberties on the x-axis, one line per level of state ownership. This is the mirror image of the lecture's plot.
grid <- expand.grid(
  mc_civ   = seq(min(Dat$mc_civ), max(Dat$mc_civ), length.out = 50),
  mc_state = c(-sd_s, 0, sd_s)
)
grid$poverty <- predict(ols_int, newdata = grid)
grid$Ownership <- factor(grid$mc_state,
  labels = c("Low", "Average", "High"))

ggplot(grid, aes(x = mc_civ, y = poverty, color = Ownership)) +
  geom_line(linewidth = 1.1) +
  labs(x = "Civil liberties (centred)",
       y = "Predicted % below $3.00 a day",
       color = "State ownership") +
  theme_minimal(base_size = 14)
  1. Now the decision that matters. Look back at the model table from task 2. Is the interaction term statistically significant at the 5% level?

  2. Write one sentence as a # comment stating what you may — and may not — conclude from this analysis. Then compare:

The fitted lines fan out, which suggests that civil liberties are more strongly associated with lower poverty where state ownership is high. But the interaction term is not statistically significant (p ≈ 0.24), so we cannot conclude that the civil-liberties slope genuinely depends on state ownership — the fanning may just be sampling noise. A suggestive picture is a hypothesis, not a finding. And even had it been significant, this is a cross-country association, not evidence about which variable causes which.

  1. Bonus, for the fast. Confirm the symmetry numerically: the interaction coefficient is identical whether you write mc_state * mc_civ or mc_civ * mc_state. Fit both and compare.
coef(lm_robust(poverty ~ mc_state * mc_civ, data = Dat))["mc_state:mc_civ"]
coef(lm_robust(poverty ~ mc_civ * mc_state, data = Dat))["mc_civ:mc_state"]

They are the same number: mc_state:mc_civ and mc_civ:mc_state are one and the same product column. "Which variable moderates which" is a story we tell, not something the maths distinguishes.

  1. Discuss with your neighbour.

    • You read the same interaction two ways (lecture: state-ownership slope by civil liberties; here: civil-liberties slope by state ownership). Which framing is "correct"?
    • The interaction was not significant. Would collecting more country-years be a legitimate way to "get" a significant result?
    • When is a non-significant interaction still worth reporting?