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
# Bali terror attack, and the ESS fieldwork window around it
event_date_begin <- as.Date("2002-09-14")
event_date <- as.Date("2002-10-13")
event_date_end <- as.Date("2002-10-20")
ESS <- ESS_raw %>%
mutate(
# Day of the survey interview
int_date = sprintf("%s-%s-%s", inwyr, inwmm, inwdd) %>% as.Date(),
# Treatment indicator
treat = case_when(
int_date > event_date & int_date <= event_date_end ~ "After the attack",
int_date < event_date & int_date > event_date_begin ~ "Before the attack",
TRUE ~ as.character(NA)) %>% fct_relevel("Before the attack", "After the attack"),
# Attitudes towards immigrants: the average of 7 items, z-standardised
anti_immi = rowMeans(select(., imtcjob, imbleco, imbgeco, imueclt,
imwbcnt, imwbcrm, imbghct), na.rm = TRUE) %>%
scale() %>% as.numeric(),
# Subtract from max to make larger values more xenophobic
anti_immi = max(anti_immi, na.rm = TRUE) - anti_immi,
# Immigrant origin
brncntr = as_factor(brncntr),
mocntr = as_factor(mocntr),
facntr = as_factor(facntr),
# Weights
pspwght = pweight * dweight) %>%
# Sample restriction: mainstream members (no immigrant origin) in Portugal
filter(str_detect(cntry, "PT") &
brncntr == "yes" & mocntr == "yes" & facntr == "yes") %>%
# Keep only the variables we need
select(treat, anti_immi, cntry, pspwght) %>%
drop_na() # Delete cases with missing values
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 <- ESS_raw %>%
mutate(
# Day of the survey interview
int_date = sprintf("%s-%s-%s", inwyr, inwmm, inwdd) %>% as.Date(),
# Treatment indicator
treat = case_when(
int_date > event_date & int_date <= event_date_end ~ "After the attack",
int_date < event_date & int_date > event_date_begin ~ "Before the attack",
TRUE ~ as.character(NA)) %>% fct_relevel("Before the attack", "After the attack"),
# Attitudes towards immigrants: the average of 7 items, z-standardised
anti_immi = rowMeans(select(., imtcjob, imbleco, imbgeco, imueclt,
imwbcnt, imwbcrm, imbghct), na.rm = TRUE) %>%
scale() %>% as.numeric(),
# Subtract from max to make larger values more xenophobic
anti_immi = max(anti_immi, na.rm = TRUE) - anti_immi,
# Immigrant origin
brncntr = as_factor(brncntr),
mocntr = as_factor(mocntr),
facntr = as_factor(facntr),
# Weights
pspwght = pweight * dweight) %>%
# Sample restriction: mainstream members (no immigrant origin) in Portugal and Sweden
filter(str_detect(cntry, "PT|SE") &
brncntr == "yes" & mocntr == "yes" & facntr == "yes") %>%
# Keep only the variables we need
select(treat, anti_immi, cntry, pspwght) %>%
drop_na() # Delete cases with missing values
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): put Portugal and Sweden side
by side in one modelsummary() table, as in
earlier lectures. Where exactly do the two countries differ?
modelsummary(list("Portugal" = ols_pt, "Sweden" = ols_se), stars = TRUE,
coef_rename = c("treatAfter the attack" = "After the attack"),
gof_map = c("nobs", "r.squared"))
| Portugal | Sweden | |
|---|---|---|
| + p < 0.1, * p < 0.05, ** p < 0.01, *** p < 0.001 | ||
| (Intercept) | 3.621*** | 3.096*** |
| (0.082) | (0.080) | |
| After the attack | 0.330** | 0.011 |
| (0.116) | (0.103) | |
| Num.Obs. | 291 | 328 |
| R2 | 0.032 | 0.000 |
The attack coefficient is about 0.33 SD and significant in Portugal, but only 0.01 SD and not significant in Sweden. Next week you will learn to show two models in one coefficient plot.