library(tidyverse)
library(targets)
library(modelsummary)
library(tinytable)
library(scales)
library(ggdag)
library(dagitty)
library(parameters)
tar_config_set(
store = here::here('_targets'),
script = here::here('_targets.R')
)
<- tar_read(data_did)
did
invisible(list2env(tar_read(graphic_functions), .GlobalEnv))
set_annotation_fonts()
<- tribble(
gof_map ~raw, ~clean, ~fmt, ~omit,
"nobs", "N", 0, FALSE,
"r.squared", "$R^2$", 2, FALSE,
"adj.r.squared", "\\(R^2\\) adjusted", 2, FALSE
)
Difference-in-differences
Parallel trends
|>
did group_by(school, year) |>
summarize(mean = ggplot2::mean_se(prosocial_index, mult = 1.96)) |>
unnest(mean) |>
ggplot(aes(x = year, y = y, color = school)) +
geom_vline(xintercept = 2022.5, linetype = "dashed") +
geom_line(linewidth = 0.25, show.legend = FALSE) +
geom_pointrange(aes(ymin = ymin, ymax = ymax)) +
scale_color_manual(values = c(clrs$Prism[2], clrs$Prism[8])) +
labs(x = NULL, y = "Prosocial index", color = NULL) +
theme_np(base_size = 16)
Models
<- lm(
model_small ~ school + factor(year) + school*factor(year),
prosocial_index data = filter(did, year %in% c(2022, 2023))
)
<- lm(
model_small_controls ~ school + factor(year) + school*factor(year) +
prosocial_index + age + gpa + income,
social_awareness data = filter(did, year %in% c(2022, 2023))
)
<- lm(
model_full ~ school + factor(year) + I(school == "School B" & year >= 2023),
prosocial_index data = did
)
<- lm(
model_full_controls ~ school + factor(year) + I(school == "School B" & year >= 2023) +
prosocial_index + age + gpa + income,
social_awareness data = did
)
<- list(
models "Interaction term only" = model_small,
"Interaction term + covariates" = model_small_controls,
"Interaction term only (all years)" = model_full,
"Interaction term + covariates (all years)" = model_full_controls
)
modelsummary(
models,statistic = "[{conf.low}, {conf.high}]",
fmt = 2,
gof_map = gof_map,
add_columns = tibble("True effect" = c(NA, NA, 10)) |> magrittr::set_attr("position", 2)
# |> )
True effect | Interaction term only | Interaction term + covariates | Interaction term only (all years) | Interaction term + covariates (all years) | |
---|---|---|---|---|---|
(Intercept) | 65.63 | -4.00 | 61.82 | -7.44 | |
[63.91, 67.34] | [-11.07, 3.07] | [60.42, 63.21] | [-12.08, -2.80] | ||
schoolSchool B | 10.00 | 1.81 | 1.73 | 3.02 | 2.14 |
[-0.62, 4.24] | [0.21, 3.24] | [1.63, 4.41] | [1.27, 3.01] | ||
factor(year)2023 | -0.18 | 1.09 | 3.86 | 4.47 | |
[-2.61, 2.25] | [-0.44, 2.61] | [1.83, 5.89] | [3.21, 5.74] | ||
schoolSchool B × factor(year)2023 | 10.47 | 8.30 | |||
[7.04, 13.90] | [6.14, 10.45] | ||||
social_awareness | 0.47 | 0.47 | |||
[0.43, 0.51] | [0.44, 0.49] | ||||
age | 0.69 | 0.64 | |||
[0.47, 0.91] | [0.50, 0.78] | ||||
gpa | 3.29 | 3.82 | |||
[2.33, 4.25] | [3.18, 4.45] | ||||
income | 0.00 | 0.00 | |||
[0.00, 0.00] | [0.00, 0.00] | ||||
factor(year)2021 | 1.77 | 1.71 | |||
[0.06, 3.47] | [0.65, 2.77] | ||||
factor(year)2022 | 3.21 | 3.15 | |||
[1.50, 4.91] | [2.08, 4.21] | ||||
factor(year)2024 | 5.25 | 6.16 | |||
[3.22, 7.28] | [4.89, 7.43] | ||||
I(school == "School B" & year >= 2023)TRUE | 8.80 | 7.76 | |||
[6.60, 11.00] | [6.39, 9.14] | ||||
N | 504 | 504 | 1260 | 1260 | |
$R^2$ | 0.21 | 0.70 | 0.24 | 0.70 | |
\(R^2\) adjusted | 0.21 | 0.70 | 0.23 | 0.70 |
# style_tt(
# i = 3:4, j = 1:6,
# background = clrs$Prism[6], color = "#ffffff", bold = TRUE
# )
modelsummary(
models,statistic = "[{conf.low}, {conf.high}]",
fmt = 2,
coef_map = c(
`schoolSchool B:factor(year)2023` = "School B × 2023",
`I(school == "School B" & year >= 2023)TRUE` = "School B × 2023"
),gof_map = gof_map,
add_columns = tibble("True effect" = 10) |> magrittr::set_attr("position", 2)
)
True effect | Interaction term only | Interaction term + covariates | Interaction term only (all years) | Interaction term + covariates (all years) | |
---|---|---|---|---|---|
School B × 2023 | 10.00 | 10.47 | 8.30 | 8.80 | 7.76 |
[7.04, 13.90] | [6.14, 10.45] | [6.60, 11.00] | [6.39, 9.14] | ||
N | 504 | 504 | 1260 | 1260 | |
$R^2$ | 0.21 | 0.70 | 0.24 | 0.70 | |
\(R^2\) adjusted | 0.21 | 0.70 | 0.23 | 0.70 |
<- enframe(models) |>
treatment_effects mutate(params = map(value, \(x) model_parameters(x))) |>
unnest(params) |>
filter(Parameter %in% c("schoolSchool B:factor(year)2023", 'I(school == "School B" & year >= 2023)TRUE')) |>
mutate(name = factor(name, levels = names(models)))
ggplot(treatment_effects, aes(x = Coefficient, y = fct_rev(name))) +
geom_vline(xintercept = 10, color = clrs$Prism[2]) +
geom_pointrange(aes(xmin = CI_low, xmax = CI_high)) +
labs(x = "Treatment effect", y = NULL) +
theme_np(base_size = 16) +
theme(panel.grid.major.y = element_blank())