Legewie_ESS_02.dta from Absalon, then copy in
this starter code. It defines the attack window and prepares the data —
keeping only Portuguese mainstream respondents:pacman::p_load(tidyverse, haven, estimatr, modelsummary)
ESS_raw <- read_dta("Legewie_ESS_02.dta") # from your project folder
event_date <- as.Date("2002-10-13") # the Bali attack
win_begin <- as.Date("2002-09-14")
win_end <- as.Date("2002-10-20")
prepare <- function(data, countries) {
data %>%
mutate(
int_date = as.Date(sprintf("%s-%s-%s", inwyr, inwmm, inwdd)),
treat = case_when(
int_date > event_date & int_date <= win_end ~ "After the attack",
int_date < event_date & int_date > win_begin ~ "Before the attack",
TRUE ~ NA_character_) %>% fct_relevel("Before the attack", "After the attack"),
# Anti-immigrant index: average 7 items, z-standardise, flip so high = xenophobic
anti_immi = rowMeans(across(c(imtcjob, imbleco, imbgeco, imueclt,
imwbcnt, imwbcrm, imbghct)), na.rm = TRUE) %>%
scale() %>% as.numeric(),
anti_immi = max(anti_immi, na.rm = TRUE) - anti_immi,
across(c(brncntr, mocntr, facntr), as_factor),
pspwght = pweight * dweight
) %>%
filter(str_detect(cntry, countries) & # <- sample restriction
brncntr == "yes" & mocntr == "yes" & facntr == "yes") %>%
select(treat, anti_immi, cntry, pspwght) %>%
drop_na()
}
ESS <- prepare(ESS_raw, "PT") # Portugal only
Stuck?
read_dta()can't find the file?Legewie_ESS_02.dtamust sit in your project folder.- Odd results? Session → Restart R, then rerun from the top.
- Still stuck? Ask in the t-R-ouble forum on Absalon.
anti_immi on treat. Among the Portuguese,
the average causal effect of the Bali attack is
standard deviations (two digits; point or comma is fine).ols_pt <- lm_robust(anti_immi ~ treat, data = ESS, weights = pspwght)
modelsummary(list("Xenophobia (PT)" = ols_pt), stars = TRUE,
coef_rename = c("treatAfter the attack" = "After the attack"),
gof_map = c("nobs", "r.squared"))
| Xenophobia (PT) | |
|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | |
| (Intercept) | 3.621*** |
| (0.082) | |
| After the attack | 0.330** |
| (0.116) | |
| Num.Obs. | 291 |
| R2 | 0.032 |
Its standard error is — less than half the coefficient, so the effect is statistically significant (the t-value clears the usual threshold of ).
Make a coefficient plot of the Portuguese effect (drop the intercept).
plotdata_pt <- ols_pt %>% tidy() %>%
filter(term != "(Intercept)") %>%
mutate(term = "After the attack", cntry = "Portugal")
ggplot(plotdata_pt, aes(y = estimate, x = cntry,
ymin = conf.low, ymax = conf.high)) +
geom_hline(yintercept = 0, color = "#901A1E", lty = "dashed") +
geom_pointrange() + coord_flip() +
labs(x = "", y = "Change in xenophobia after the attack (SD)") +
theme_minimal()
"PT|SE", then estimate the effect for Sweden only
(data = ESS2 %>% filter(cntry == "SE")). The Swedish
effect is
,
and it is
.ESS2 <- prepare(ESS_raw, "PT|SE")
ols_se <- lm_robust(anti_immi ~ treat, data = ESS2 %>% filter(cntry == "SE"),
weights = pspwght)
modelsummary(list("Xenophobia (SE)" = ols_se), stars = TRUE,
coef_rename = c("treatAfter the attack" = "After the attack"),
gof_map = c("nobs", "r.squared"))
| Xenophobia (SE) | |
|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | |
| (Intercept) | 3.096*** |
| (0.080) | |
| After the attack | 0.011 |
| (0.103) | |
| Num.Obs. | 328 |
| R2 | 0.000 |
# comment)
comparing the two countries, then check:The Bali attack raised xenophobia by about 0.33 SD in Portugal (significant) but only 0.01 SD in Sweden (not significant) — the same shock produced different reactions in different societies. Look at you: this is exactly the kind of natural-experiment analysis published in the American Journal of Sociology.
Bonus (for the fast): combine both into one
coefficient plot with
bind_rows(plotdata_pt, plotdata_se, .id = "id") and colour
by country.
plotdata_se <- ols_se %>% tidy() %>%
filter(term != "(Intercept)") %>% mutate(cntry = "Sweden")
bind_rows(plotdata_pt, plotdata_se) %>%
ggplot(aes(y = estimate, x = reorder(cntry, estimate),
ymin = conf.low, ymax = conf.high)) +
geom_hline(yintercept = 0, color = "#901A1E", lty = "dashed") +
geom_pointrange() + coord_flip() +
labs(x = "", y = "Change in xenophobia after the attack (SD)") +
theme_minimal()