library(tidyverse) # ggplot, dplyr, and friends
library(broom) # Convert models to data frames
library(scales) # This makes it easy to format numbers with dollar(), comma(), etc.
library(ggdag) # Draw causal diagrams with R
library(modelsummary) # Fancy regression tablesResultados Potenciales, ATEs, y CATEs
Teoría
Asumamos que existe una teoría que nos dice que asistir a una universidad privada debería estar causalmente vinculado con los ingresos y las ganancias; es decir, asistir a una escuela privada debería generar mayores ingresos. Sin embargo, el tipo de educación que se recibe no es el único factor que influye en los ingresos. Las personas se autoseleccionan en diferentes tipos de universidades, eligen dónde solicitar admisión y qué ofertas aceptar. También optan por no solicitar admisión en algunas escuelas y son rechazadas en otras. Las características no medidas ayudan a determinar tanto la admisión en las escuelas como los ingresos.
Podemos dibujar una versión simplificada de esta historia causal con un gráfico acíclico dirigido (DAG) o modelo causal:
dag <- dagify(Y ~ P + G,
P ~ G,
exposure = "P",
outcome = "Y",
labels = c(Y = "Earnings", P = "Private university",
G = "Student characteristics (group)"),
coords = list(x = c(Y = 3, P = 1, G = 2),
y = c(Y = 1, P = 1, G = 2)))
ggdag_status(dag, use_labels = "label") +
guides(color = "none") + # Remove legend
theme_dag()Efecto de la escuela privada sobre los ingresos, sin controles
Como no tenemos una máquina del tiempo, no podemos analizar contrafactuales a nivel individual: no podemos enviar a la Persona 1 a una escuela privada, observarla durante 40 años y luego regresar a una escuela pública para observarla durante 40 años. Para solucionar esto, podemos calcular el efecto promedio del tratamiento (EPT) y hallar el promedio de todos los efectos causales a nivel individual.
Podemos usar la información del DAG de nuestra teoría para calcular un EPT (¡ojalá!) preciso.
Primero cargamos los datos de este archivo CSV (‘public_private_earnings’):
# The data doesn't come with an indicator variable marking if students went to a
# private school, so we create one here. If the string "ivy" is found in the
# enrolled column, mark it as true, otherwise mark it as false.
#
# We also create a variable that indicates if someone is in group A or not that
# we'll use in the regression models. We could technically just include the
# group variable in the model, where it would be treated as a dummy variable,
# but the reference category would be A, not B, so this is a little trick to
# force it to show results for group A.
schools <- read_csv("data/public_private_earnings.csv") %>%
mutate(private = ifelse(str_detect(enrolled, "ivy"), TRUE, FALSE)) %>%
mutate(group_A = ifelse(group == "A", TRUE, FALSE))
# Only look at groups A and B, since C and D don't have people in both public
# and private schools. | means "or"
schools_small <- schools %>%
filter(group == "A" | group == "B")Es realmente tentador encontrar el ingreso promedio de la escuela privada y restarlo del de la escuela pública, de la siguiente manera:
schools_small %>%
group_by(private) %>%
summarize(avg_earnings = mean(earnings))
## # A tibble: 2 × 2
## private avg_earnings
## <lgl> <dbl>
## 1 FALSE 70000
## 2 TRUE 90000Parece que quienes fueron a escuelas privadas ganan $20,000 más. Pero este resultado es totalmente erróneo . ¡No lo hagan! Esto no explica ningún factor de confusión ni sesgo de selección. Según nuestro DAG, las características de los estudiantes son un factor de confusión importante. Debemos tenerlas en cuenta.
Siguiendo el marco de resultados potenciales, podemos determinar el ATE combinando los ATE condicionales (o CATE) de los subgrupos que probablemente predigan resultados o que agrupen observaciones similares. En este caso, utilizaremos la distinción entre los grupos A y B como subgrupos.
Primero podemos observar el ingreso promedio de las personas de cada grupo, dividido según si asistieron a una escuela privada o pública:
avg_earnings <- schools_small %>%
group_by(group, private) %>%
summarize(avg_earnings = mean(earnings))
avg_earnings
## # A tibble: 4 × 3
## # Groups: group [2]
## group private avg_earnings
## <chr> <lgl> <dbl>
## 1 A FALSE 110000
## 2 A TRUE 105000
## 3 B FALSE 30000
## 4 B TRUE 60000Aquí vemos que el grupo A tiene ingresos más altos en promedio que el grupo B, independientemente de si asistieron a una escuela privada. Todos en el grupo A ganan aproximadamente $100,000, mientras que los del grupo B ganan mucho menos.
Podemos encontrar las diferencias exactas en las ganancias del sector público frente al privado dentro de cada grupo extrayendo los valores de la tabla y tomando sus diferencias.
# Pulling out each of the numbers is tedious and a good example of why we use
# regression instead. filter() selects rows that match the specified conditions
# (here where group and private both equal something) and pull extracts a column
# from the dataset. Because we're filtering this data in a way that makes it
# only have one row, pull() will extract a single number.
# Group A
income_private_A <- avg_earnings %>%
filter(group == "A" & private == TRUE) %>%
pull(avg_earnings)
income_public_A <- avg_earnings %>%
filter(group == "A" & private == FALSE) %>%
pull(avg_earnings)
cate_a <- income_private_A - income_public_A
cate_a
## [1] -5000
# Group B
income_private_B <- avg_earnings %>%
filter(group == "B" & private == TRUE) %>%
pull(avg_earnings)
income_public_B <- avg_earnings %>%
filter(group == "B" & private == FALSE) %>%
pull(avg_earnings)
cate_b <- income_private_B - income_public_B
cate_b
## [1] 30000La brecha de ingresos entre el sector público y el privado para las personas del Grupo A (o) es de − $ 5,000, mientras que para el Grupo B (o) son 30.000 dólares . Parece que hay un gran efecto para el Grupo B, pero un pequeño efecto inverso para el A.
Queremos tener en cuenta cuántas personas hay en cada grupo, ya que A tiene más personas que B, así que calculamos la proporción de cada grupo en el mismo y multiplicamos las diferencias de grupo por esas proporciones.
\[ \text{ATE} = \pi_\text{Group A} \text{CATE}_\text{Group A} + \pi_\text{Group B} \text{CATE}_\text{Group B} \]
# We need to find the proportion of people in each group
prop_in_groups <- schools_small %>%
group_by(group) %>%
summarize(n = n()) %>%
mutate(prop = n / nrow(schools_small))
prop_in_groups
## # A tibble: 2 × 3
## group n prop
## <chr> <int> <dbl>
## 1 A 3 0.6
## 2 B 2 0.4
prop_A <- prop_in_groups %>% filter(group == "A") %>% pull(prop)
prop_B <- prop_in_groups %>% filter(group == "B") %>% pull(prop)
# With those proportions, we can weight the differences in groups correctly
weighted_effect <- (cate_a * prop_A) + (cate_b * prop_B)
weighted_effect
## [1] 9000Efecto de la escuela privada sobre los ingresos, con regresión y controles
En lugar de mirar promedios ponderados (ya que eso es tedioso con solo dos grupos, ¡imagínense hacer todo eso con más de 3 grupos!), podemos usar un modelo de regresión que tenga en cuenta las diferencias entre los grupos A y B, ya que algo en el grupo A los hizo mucho más ricos que el grupo B independientemente del tipo de escuela.
Lo hacemos prediciendo las ganancias en función de la asistencia a escuelas privadas o públicas y al mismo tiempo controlando el grupo:
model_earnings <- lm(earnings ~ private + group_A, data = schools_small)tidy(model_earnings)
## # A tibble: 3 × 5
## term estimate std.error statistic p.value
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 (Intercept) 40000. 11952. 3.35 0.0789
## 2 privateTRUE 10000. 13093. 0.764 0.525
## 3 group_ATRUE 60000 13093. 4.58 0.0445Aquí hay tres números importantes. La intersección es de $40,000. Esto representa las ganancias de alguien con todos los interruptores y controles deslizantes del modelo configurados en 0 o desactivados; en este caso, alguien que asistió a una escuela pública del grupo B.
El coeficiente group_Amuestra el efecto de pertenecer a ese grupo. Por alguna razón, el Grupo A gana un promedio de $60,000 más que el Grupo B, por razones distintas a la educación . Esto nos permite controlar el efecto de la selección.
El coeficiente para privatees el que más nos importa: este es el efecto causal de las escuelas privadas sobre los ingresos (suponiendo que podemos justificar todos los controles y la asignación a grupos). Es de $ 10,000, lo que significa que asistir a una escuela privada proporciona un aumento considerable en los ingresos. Este valor es mayor que los $ 9,000 que encontramos anteriormente, pero probablemente sea más preciso, ya que consideramos otras diferencias ponderadas entre los grupos.