knitr::opts_chunk$set(fig.retina = 3,
                      fig.align = "center", out.width = "100%")

library(tidyverse)
library(ggdag)
library(dagitty)

update_geom_defaults(ggdag:::GeomDagText, list(family = "Noto Sans", face = "plain"))

In this project, we want to know the causal effect of anti-NGO laws on foreign aid. If a country passes a new anti-NGO law, or if the general environment for NGOS and civil society worsens in a year, do donor countries reduce their allocated aid in following years? More specifically, what is the effect of treatment (NGO laws or the civil society environment) in time \(t-1\) on foreign aid in time \(t\)?

Doing this is tricky though because (1) it involves time series cross sectional data, (2) treatment history matters, and (3) treatment can either be binary (new law vs. no new law) or continuous (total count of laws, or a continuous measure of civil society openness).

Ultimately, we’re using a MSM like this to estimate the causal effect. The treatment model accounts for a bunch of confounders across three broader categories: (1) human rights and politics (like corruption, level of democracy, etc.), (2) economics and development (like trade, mortality, etc.), and (3) unexpected shocks (like natural disasters). This is based on the following DAG:

simplerish_dag <- dagitty('
dag {
"`Human rights & politics`[t-1]" [adjusted,pos="5,1.5"]
"`Human rights & politics`[t-i]" [pos="1,1.5"]
"`Human rights & politics`[t]" [pos="9,1.5"]
"`Economics & development`[t-1]" [adjusted,pos="5,2.5"]
"`Economics & development`[t-i]" [pos="1,2.5"]
"`Economics & development`[t]" [pos="9,2.5"]
"Outcome[t-1]" [pos="6.5,1.75"]
"Outcome[t-i]" [adjusted,pos="2.5,1.75"]
"Outcome[t]" [outcome,pos="10.5,1.75"]
"Restrictions[t-1]" [exposure,pos="6,2.25"]
"Restrictions[t-i]" [adjusted,pos="2,2.25"]
"Restrictions[t]" [pos="10,2.25"]
"`Unexpected shocks`[t-1]" [adjusted,pos="5,2"]
"`Unexpected shocks`[t-i]" [pos="1,2"]
"`Unexpected shocks`[t]" [pos="9,2"]
"`Human rights & politics`[t-1]" -> "`Human rights & politics`[t]"
"`Human rights & politics`[t-1]" -> "Outcome[t-1]"
"`Human rights & politics`[t-1]" -> "Restrictions[t-1]"
"`Human rights & politics`[t-1]" -> "Restrictions[t]"
"`Human rights & politics`[t-i]" -> "`Human rights & politics`[t-1]"
"`Human rights & politics`[t-i]" -> "Outcome[t-i]"
"`Human rights & politics`[t-i]" -> "Restrictions[t-i]"
"`Human rights & politics`[t]" -> "Outcome[t]"
"`Human rights & politics`[t]" -> "Restrictions[t]"
"`Economics & development`[t-1]" -> "`Economics & development`[t]"
"`Economics & development`[t-1]" -> "Outcome[t-1]"
"`Economics & development`[t-1]" -> "Restrictions[t-1]"
"`Economics & development`[t-1]" -> "Restrictions[t]"
"`Economics & development`[t-i]" -> "`Economics & development`[t-1]"
"`Economics & development`[t-i]" -> "Outcome[t-i]"
"`Economics & development`[t-i]" -> "Restrictions[t-i]"
"`Economics & development`[t]" -> "Outcome[t]"
"`Economics & development`[t]" -> "Restrictions[t]"
"Outcome[t-1]" -> "Outcome[t]"
"Outcome[t-1]" -> "Restrictions[t]"
"Outcome[t-i]" -> "Outcome[t-1]"
"Outcome[t-i]" -> "Restrictions[t-1]"
"Restrictions[t]" -> "Outcome[t]"
"Restrictions[t-1]" -> "Outcome[t-1]"
"Restrictions[t-i]" -> "Outcome[t-i]"
"Restrictions[t-1]" -> "Outcome[t]"
"Restrictions[t-1]" -> "Restrictions[t]"
"Restrictions[t-i]" -> "Outcome[t-1]"
"Restrictions[t-i]" -> "Restrictions[t-1]"
"`Unexpected shocks`[t-1]" -> "Outcome[t-1]"
"`Unexpected shocks`[t-1]" -> "Restrictions[t-1]"
"`Unexpected shocks`[t-1]" -> "Restrictions[t]"
"`Unexpected shocks`[t-1]" -> "`Unexpected shocks`[t]"
"`Unexpected shocks`[t-i]" -> "Outcome[t-i]"
"`Unexpected shocks`[t-i]" -> "Restrictions[t-i]"
"`Unexpected shocks`[t-i]" -> "`Unexpected shocks`[t-1]"
"`Unexpected shocks`[t]" -> "Outcome[t]"
"`Unexpected shocks`[t]" -> "Restrictions[t]"
}
')

simplerish_dag_plot <- simplerish_dag %>% 
  tidy_dagitty() %>% 
  mutate(var_type = case_when(
    str_detect(name, "Outcome") ~ "Outcome",
    str_detect(name, "Restrictions") ~ "Restrictions",
    TRUE ~ "Z"
  )) %>% 
  mutate(time_period = case_when(
    str_detect(name, "t-1") ~ 2,
    str_detect(name, "t-i") ~ 1,
    TRUE ~ 3
  )) %>% 
  mutate(arrow_color = case_when(
    name == "Restrictions[t-1]" & to == "Outcome[t]" ~ "#FF4136",
    TRUE ~ "grey60"
  ))

ggplot(simplerish_dag_plot, aes(x = x, y = y, xend = xend, yend = yend)) +
  geom_dag_edges(aes(edge_colour = arrow_color)) +
  geom_dag_point(aes(color = var_type, alpha = time_period), size = 12) +
  geom_dag_text(data = filter(simplerish_dag_plot, var_type == "Outcome"),
                color = "black", size = 3, parse = TRUE) +
  geom_dag_text(data = filter(simplerish_dag_plot, var_type == "Restrictions"),
                color = "black", size = 3, parse = TRUE) +
  geom_dag_text(data = filter(simplerish_dag_plot, var_type == "Z"),
                color = "black", size = 3, parse = TRUE) +
  scale_color_manual(values = c("#B10DC9", "#FF851B", "grey60")) +
  scale_y_reverse() +
  guides(alpha = "none", color = "none") +
  theme_dag()