Regressão com Descontinuidade

Author

Igor Viveiros e João Camargos

Published

August 11, 2023

1 Regressão com Descontiuidade

A última aula será dedicada a demostrar a utilização de modelos de Regressão com Descontinuidade (RDD). Utilizaremos como exemplo o conjunto de dados para mensurar o efeito da idade legal em acidentes de carro (Carpenter & Dobkin 2011).

  • Pergunta de pesquisa: Qual o impacto de ter idade para beber alcool sobre o número de mortes no transito?

-Em um esforço para lidar com os problemas sociais e de saúde pública associados ao consumo de álcool por menores de idade, um grupo de presidentes de universidades americanas fez lobby junto aos estados para que o limite mínimo legal de idade para consumir álcool (MLDA, na sigla em inglês) retorne ao limiar da era do Vietnã, que era de 18 anos. A teoria por trás desse esforço (conhecido como Iniciativa Amethyst) é que permitir o consumo legal de álcool a partir dos 18 anos desencoraja o consumo excessivo e promove uma cultura de consumo maduro de bebidas alcoólicas. Isso contrasta com a visão tradicional de que o MLDA de 21 anos, embora uma ferramenta direta e imperfeita, reduz o acesso dos jovens ao álcool, prevenindo assim alguns danos. Angrist e Pischke (2014).

  • Para responder a pergunta Carpenter e Dobkin (2011) buscaram dados nos Estados Unidos, em que a idade para dirigir começa aos 16 anos mas o consumo de bebida só é legalizado a partir dos 21 anos. Assim, se torna uma oportunidade para a aplicação de RDD a fim de avaliar o impacto da MLDA nas mortes em transito.
Code
# Pacotes utilizados
library(tidyverse)
library(rdrobust)
library(readr)
library(sjPlot)
library(broom)
library(estimatr) 
set.seed(42)

# Download do banco de dados

mlda_df <- readr::read_csv("https://raw.githubusercontent.com/seramirezruiz/stats-ii-lab/master/Session%206/data/mlda.csv")

mlda_df <- mlda_df |> 
  select(c(outcome, agecell, treatment, forcing))

sample_n(mlda_df, 5) |> tab_df(title = "Estrutura do banco") 
Estrutura do banco
outcome agecell treatment forcing
31.83 22.03 1 1.03
35.83 19.07 0 -1.93
36.32 21.04 1 0.04
30.58 19.81 0 -1.19
31.54 21.95 1 0.95
  • No banco exposto, a variável \(outcome\) é o número de mortes no trânsito por 100 mil habitantes, \(agecell\) é a faixa de idade, \(treatment\) indica que a faixa é maior do que 21 anos e \(forcing\) é a variável padronizada a fim de 21 anos ser equivalente a zero e a variação se manter entre 2 e menos 2, sendo essa a variável de atribuição.Podemos imaginar que a variável \(D\) define o recebimento ou não do tratamento, de modo que:

\(D = 1\) se \(X\geq c\)

\(D = 0\) se \(X< c\)

  • Em que \(X\) é a variável de atribuição e \(C\) é o ponto de corte. A RDD é baseada em uma hipóteses:

  • Hipótese 1: Todos os outros fatores (que não \(D\)) estão evoluindo de maneira suave em torno de \(c\).

  • Essa deriva em duas outras:

  • Hipótese 2.1: Funções de regressões condicionais contÌnuas: \(E[Y (0)| X = x]\) e E \([Y (1)| X = x]\) são contínuas em \(x\).

  • Hipótese 2.2: Funções de regressões condicionais contÌnuas: \(F_{Y(0)|x}(y|x)\) e \(F_{Y(1)|x}(y|x)\) são funções continuas em \(x\) para todo \(y\).

  • É possível supor que o comportamento dos indivíduos entre 19 e 23 anos não sofre grandes alterações, devido a proxímidade da idade, de modo que atendemos as hipóteses necessárias. O segundo passo é determinar qual desing Caso \(c\) seja claro, ou seja um ponto específico marque o corte e nada antes dele receba o tratamento e todos depois dele recebam, temos um modelo com o set up de um modelo \(sharp\). Se a linha de corte não é clara, ou seja, existam individuos que recebem e não recebem o tratamento na mesma etapa, temos um setup \(fuzzy\).

Code
library(tidyverse)
library(gridExtra)

# Criando a base de dados simulada com mais pontos
data_fuzzy <- tibble(
  d = c(rep(50,x= 0),rep(50,x= 1)),
  x = c(rnorm(40,10, 2),rnorm(20,15,2),rnorm(40,20, 2)),
  eps = rnorm(100,0,15),
  y = x*40+ d*60 + eps
)


# Visualização Fuzzy set
g1 <- ggplot(data_fuzzy, aes(x = x, y = as.factor(d))) +
  geom_point() +
  geom_vline(xintercept = 15, color = "red", linetype = "dashed") +
  labs(x = "X", y = "D", title = "Dados em um fuzzy set")+
  theme_bw()

g1.1 <- ggplot(data_fuzzy, 
       aes(x = x, 
           y = y, 
           color = as.factor(d))) + 
  geom_point() +
  geom_vline(xintercept = 15, linetype = "dotted") +
  theme_bw()+
  labs(color = "D")

# Visualização Sharp set
g2 <- data_fuzzy |> 
  filter(x > 15 & d==1|x < 15 & d==0) |> 
  ggplot(aes(x = x, y = as.factor(d))) +
  geom_point() +
  geom_vline(xintercept = 15, color = "red", linetype = "dashed") +
  labs(x = "X", y = "D", title = "Dados em um sharp set")+
  theme_bw()

g2.1 <- data_fuzzy |> 
  filter(x > 15 & d==1|x < 15 & d==0) |> 
  ggplot(aes(x = x, 
           y = y, color = as.factor(d))) + 
  geom_point() +
  geom_vline(xintercept = 15, linetype = "dotted") +
  labs(color = "D")+
  theme_bw()

grid.arrange(g2,g1,g2.1,g1.1, ncol = 2)

  • O primeiro passo é avaliar se aplicaremos uma RDD do tipo \(sharp\) ou do tipo \(fuzzy\). No caso, o corte na lei é claro, legalizando o consumo de alcool no momento em que o indivíduo completou 21 anos. Podemos vizualizar a propabilidade de se encaixar no tratamento a partir do seguinte gráfico:
Code
ggplot(mlda_df, aes(x = agecell, 
                 y = treatment,
                 color = factor(treatment))) +
  geom_point(size = 1.5, alpha = 0.5,
             position = position_jitter(width = 0, height = 0.25, seed = 1234)) + 
  labs(x = "Idade", 
       y = "Probabilidade de ser tratado") +
  scale_color_discrete(name = " ", 
                       labels = c("Não possui idade legal para beber", "Possui idade legal para beber")) +
  geom_vline(xintercept = 21, linetype = "dotted") +
  theme_bw()+
  theme(legend.position = "bottom")

  • Assim, o uso de uma RDD \(sharp\) é o indicado. A partir disso, analisaremos então o comportamento dos dados a fim de entender qual modelo melhor capturará a variação dos dados.
Code
ggplot(mlda_df, 
       aes(x = agecell, 
           y = outcome)) + 
  geom_point() +
  geom_vline(xintercept = 21, linetype = "dotted") +
  labs(title = "Análise exploratória",
       x = "Variável forçada (Idade)",
       y = "Taxa de mortalidade por acidentes\n de transito (por 100,000)") +
  theme_minimal()

  • Assumimos inicialmente que a relação entre \(X\) e \(Y\) seja linear, podemos estimar a relação entre o efeito do tratamento \(\tau\) por meio da seguinte regressao linear.

\[Y = \alpha + D_{\tau} + \beta X + \epsilon\]

  • Se todos os fatores variam suavemente de acorco com \(X\), então \(\beta\) seria uma boa estimativa do valor de \(X\) para quem está acima da linha de corte e \(\alpha\) para aqueles abaixo da linha de corte, de modo que o efeito causal seria dado por \(\beta X\) - \(\alpha\). Para supormos isso, é necessário que todos os fatores que afetam \(Y\) variem suavimente com \(X\). Caso isso não se confirme, \(\tau\) será estimado com viés. Assim, primeiramente, rodaremos um modelo linear com retas comuns. Observe que a variável \(forcing\) é CENTRALIZADA em 0 (idade 21) e representa a distância em anos a partir dos 21 anos, enquanto o tratamento é apenas binário, acima/abaixo de 21 anos.
Code
linear_common_slope <- lm(outcome ~ treatment + forcing, data = mlda_df)

linear_common_slope |> tab_model()
  outcome
Predictors Estimates CI p
(Intercept) 29.36 28.49 – 30.22 <0.001
treatment 4.53 2.99 – 6.08 <0.001
forcing -3.15 -3.83 – -2.47 <0.001
Observations 48
R2 / R2 adjusted 0.703 / 0.689

De acordo com nossas suposições para modelos lineares com inclinação comum, consideramos que o efeito do tratamento não depende da variável de forçamento. Podemos formalizar esse modelo da seguinte forma:

\[E(Y_i|X_i,D_i)=\tilde{\beta}_0 + \beta_1treatment_i+\beta_2\tilde{forcing}_i + \epsilon\]

  • Portanto, podemos afirmar que, com base em nosso \(\beta_1\), podemos esperar 4,53 mortes adicionais por acidentes de trânsito a cada 100.000 pessoas para aqueles que podem legalmente consumir bebidas alcoólicas. Também observamos que, para cada ano de aumento na idade, o número de mortes esperadas por 100.000 pessoas diminui em 3,15 (\(\beta_2\). Podemos extrair os valores preditos a fim de recriar o fit. Uma das melhores formas de vizualizar os resultados é dividindo o gráfico e duas janelas (bins) e plotar as linhas da regressão em ambos os casos:
Code
mlda_df$yhat_linear <- predict(linear_common_slope) # Criando uma variável com o modelo predito. 

mlda_df %>% 
  ggplot(aes(x = forcing,  
             y = yhat_linear, 
             col = factor(treatment))) +
  geom_point(aes(x = forcing, 
                 y = outcome,
                 col = factor(treatment))) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  labs(title = "Modelo linear com reta comum",
       x = "Variável forçada (Idade)",
       y = "Taxa de mortalidade por acidentes\n de transito (por 100,000)") +
  geom_line(data = mlda_df[mlda_df$forcing >= 0,], 
            color = "#cc0055",
            size = 1) +
  geom_line(data = mlda_df[mlda_df$forcing < 0,], 
            color = "#696969", 
            size = 1) +
  scale_color_manual(name = "",
                     values = c("#696969", "#cc0055"),
                     labels = c("Controle", "Tratamento")) +
  theme_bw()

  • Agora, reestimaremos essa regressão permitindo que haja variação entre as retas da regressão. Isso pode ser feito por meio da introdução de um termo interativo no modelo.

\[E(Y_i|X_i,D_i)=\tilde{\beta}_0 + \beta_1D_1+\beta_2X_i+\tilde{\beta}_3\tilde{X}_i + \epsilon\]

Code
linear_different_slope <- lm(outcome ~ treatment*forcing, data = mlda_df)

linear_different_slope |> tab_model()
  outcome
Predictors Estimates CI p
(Intercept) 29.93 28.86 – 31.00 <0.001
treatment 4.53 3.02 – 6.05 <0.001
forcing -2.57 -3.51 – -1.63 <0.001
treatment × forcing -1.16 -2.49 – 0.17 0.085
Observations 48
R2 / R2 adjusted 0.722 / 0.703

Portanto, podemos afirmar que, dado \(\beta_1\), podemos esperar 4,53 mortes adicionais por acidentes de veículos a cada 100.000 pessoas para aqueles que podem legalmente consumir bebidas alcoólicas no limite de idade. Agora temos duas inclinações diferentes para mudanças na idade. Para indivíduos com menos de 21 anos, um aumento de um ano na idade resultaria, em média, em 2,57 mortes a menos por acidentes de veículos (\(\beta_2\)). Para aqueles que têm idade legal para beber, esperaríamos 3,73 mortes a menos por 100.000 pessoas para cada aumento de um ano na idade (\(\beta_2X_i+\beta_3\tilde{X}_i\) = - 2,57 + (-1,16). Além disso, o modelo se adequou um pouco melhor aos dados, com um \(R^2\) de 0,722, sendo 0,019 maior que o modelo anterior.

Code
mlda_df %>% 
  ggplot(aes(x = forcing,  
             y = outcome, 
             col = factor(treatment))) +
  geom_point() +
  geom_vline(xintercept = 0, linetype = "dotted") +
  geom_smooth(method = "lm", se = F) +
  labs(title = "Modelo linear com retas variando",
       x = "Variável forçada (Idade)",
       y = "Taxa de mortalidade por acidentes\n de transito (por 100,000)")+
  scale_color_manual(name = "",
                     values = c("#696969", "#cc0055"),
                     labels = c("Controle", "Tratamento")) + 
  theme_bw() 

  • Podemos também deixar o tratamento variar ao longo do tratamento, respeitando as premissas de modelos não lineares. Assim, os efeitos do tratamento \(D_i\) podem variar ao longo da variável \(X_i\). No caso, estimaremos um modelo com interações quadráticas. O modelo é especificado da seguinte forma:

\[E(Y_i|X_i,D_i)=\gamma_0 + \gamma_1\tilde{X}_i+ \gamma_2\tilde{X}_i^2 + \tau_3D_i + \alpha_1\tilde{X}_iD_i +\alpha_2\tilde{X}_i^2D_i + \epsilon\]

Code
quadratic <- lm(outcome ~ forcing + 
                  I(forcing^2) + # I tells R to interpret "as is"
                  treatment + 
                  I(forcing * treatment) + 
                  I((forcing^2) * treatment),
                data = mlda_df)

quadratic |>tidy() |>  tab_df()
term estimate std.error statistic p.value
(Intercept) 29.81 0.82 36.51 0.00
forcing -2.93 1.91 -1.53 0.13
I(forcing^2) -0.19 0.94 -0.20 0.84
treatment 4.66 1.15 4.04 0.00
I(forcing * treatment) -0.82 2.71 -0.30 0.76
I((forcing^2) * treatment) 0.20 1.33 0.15 0.88
  • Portanto, podemos dizer que, considerando nosso \(\tau\), podemos esperar 4,66 mortes adicionais por acidentes de veículos a cada 100.000 pessoas para aqueles que podem legalmente consumir bebidas alcoólicas no limite de idade. Também poderíamos calcular o valor esperado de \(Y\) em diferentes níveis de \(X\).

  • Digamos que queiramos saber qual é o valor esperado para pessoas de 23 anos. Como nossa variável de forçamento é 0 aos 21 anos de idade, podemos considerar 23 como 2. Além disso, pessoas de 23 anos estão acima da idade legal mínima para beber, portanto, para elas, o valor de \(D\) é 1.

\[E(Y_i|X = 2,D = 1)= 29,8-2,93(2) - 0,19(2)^2 + 4,66(1) - 0,82(2,1)+0,2(2,1) \]

  • Com base nisso, esperaríamos uma taxa de mortalidade por acidentes de veículos de 27,01 a cada 100.000 pessoas para pessoas de 23 anos. Podemos plotar os resultados do modelo.
Code
mlda_df$yhat_quadratic <- predict(quadratic) 


mlda_df %>% 
  ggplot(aes(x = forcing, 
             y = yhat_quadratic, #note predicted y
             col = factor(treatment))) +
  geom_point(aes(x = forcing, 
                 y = outcome, 
                 col = factor(treatment))) +
  geom_vline(xintercept = 0, linetype = "dotted") +
  labs(title = "Modelo quadratico",
       x = "Variável forçada (Idade)",
       y = "Taxa de mortalidade por acidentes\n de transito (por 100,000)") +
  geom_line(data = mlda_df[mlda_df$forcing >= 0,], 
            color = "#cc0055", 
            size = 1) +
  geom_line(data = mlda_df[mlda_df$forcing < 0,], 
            color = "#696969", 
            size = 1) +
  scale_color_manual(name = "",
                     values = c("#696969", "#cc0055"),
                     labels = c("Controle", "Tratamento")) + 
  theme_minimal()

  • Podemos calcular o efeito médio causal local (Local Avarage Treatment Effect) para aqueles com mais de 21 anos por meio de uma estimação dos pontos por meio de um regressão polinomial local com correção de viés.
Code
llr <- rdrobust::rdrobust(mlda_df$outcome, 
                          mlda_df$forcing,  
                          c = 0,
                          kernel = "tri",
                          bwselect = "mserd")
summary(llr)
Sharp RD estimates using local polynomial regression.

Number of Obs.                   48
BW type                       mserd
Kernel                   Triangular
VCE method                       NN

Number of Obs.                   24           24
Eff. Number of Obs.               6            6
Order est. (p)                    1            1
Order bias  (q)                   2            2
BW est. (h)                   0.487        0.487
BW bias (b)                   0.738        0.738
rho (h/b)                     0.660        0.660
Unique Obs.                      24           24

=============================================================================
        Method     Coef. Std. Err.         z     P>|z|      [ 95% C.I. ]       
=============================================================================
  Conventional     4.901     2.059     2.380     0.017     [0.864 , 8.937]     
        Robust         -         -     1.881     0.060    [-0.198 , 9.674]     
=============================================================================
  • Os resultados apontam para um efeito não significante do tratamento para aqueles com mais de 21 anos. Podemos plotar esses resultados da seguinte forma:
Code
rdplot(mlda_df$outcome, 
                 mlda_df$forcing,  
                 c = 0,
                 kernel = "tri",
                 title = "Morte em acidentes no transito",
                 x.label = "Idade a partir de 21",
                 y.label =  "Morte em acidentes no transito (per 100,000)"
)

2 Exemplo de um fuzzy set

  • Para dar apenas um exemplo de como operar um modelo com \(fuzzy\) set. Nesse segundo exemplo, testaremos o efeito de ter aulas particulares sobre o exame de conclusão de um curso. Nesse caso, alunos que no exame de entrada tiraram menos do que 70% tem direito a uma monitoria gratuita. Assim, teoricamente temos um \(c\) bem especificado (70%), mas o tratamento está distribuido em ambas as partes do corte. O banco está nessa estrutura
Code
tutoring <- read.csv("./tutoring_program_fuzzy.csv")

sample_n(tutoring, 5) |> tab_df(title = "Estrutura do banco") 
Estrutura do banco
id entrance_exam tutoring tutoring_text exit_exam
756 89.26 TRUE Tutor 79.24
981 95.91 FALSE No tutor 61.90
404 96.92 FALSE No tutor 74.02
715 85.60 FALSE No tutor 64.01
225 70.21 FALSE No tutor 70.14
  • Contudo, ao fazer uma análise visual dos dados, vemos que não é isso que acontece:
Code
library(ggpubr)
g1 <- ggplot(tutoring, aes(x = entrance_exam, y = tutoring_text, color = entrance_exam <= 70)) +
  geom_point(size = 1.5, alpha = 0.5,
             position = position_jitter(width = 0, height = 0.25, seed = 1234)) +
  geom_vline(xintercept = 70) +
  labs(x = "Resultado no exame de entrada", y = "Participou do programa de monitoria") +
  guides(color = "none")+
  theme_bw()



g2 <- ggplot(tutoring, aes(x = entrance_exam, y = exit_exam, color = tutoring)) +
  geom_point(size = 1.5, alpha = 0.5,
             position = position_jitter(width = 0, height = 0.25, seed = 1234)) +
  geom_vline(xintercept = 70) +
  labs(x = "Resultado no exame de entrada", y = "Resultado no exame de saída") +
  guides(color = "none")+
  theme_bw()


ggarrange(g2,g1)

  • Nesse caso, 36 pessoas que deveriam ter a tutoria não a receberam e 116 pessoas que não eram elegiveis a monitoria que a receberam. Assim, o setup deixa de ser \(sharp\) e passa a ser \(fuzzy\). Assim, ao inves da propabilidade de receber o tratamento ser \(D = 1\) se \(X\geq c\) e \(D = 0\) se \(X< c\), temos apenas um pequeno aumento dessa probabilidade de um grupo para outro. Assim, utilizaremos um modelo análogo a uma variável instrumental para dividir o salto de \(Y\) sobre \(X\) com o salto da regressão do indicador do tratamento em \(X\). Para que isso seja atendido, assumimos uma terceira hipótese:

  • Hipótese 3: Monotonicidade - : Os valores de X que passam o ponto de corte não podem simultaneamente causar algumas unidades serem tratadas e outras rejeitarem o tratamento

  • Aceitando essa hipótese, dividimos nossos casos em três grupos: Compliers que respeitam o corte estimado por \(c\); Nevertakers que não recebem o tratamento, independente de estarem elegiveis ou não; e Always-takers que recebem o tratamento independente de serem elegíveis ou não.

  • Da mesma maneira que em variável instrumental, tinhamos que verificar que existia uma relção forte entre a variável endógena e o instrumento; neste caso temos que verifícar que de fato existe uma descontinuidade na expectativa de \(D\) condicional a \(X\). Assim, podemos formalizar em:

\[Y_i = \delta^{\tau}V_i + \tau\times D_i + \epsilon\]

Que pode ser estimada por uma regressão linear de 2 estágios usando \(1{x_i-c\leq0}\) como instrumento para \(D_i\). Primeiramente, centralizaremos a variável \(X\), nesse caso a nota de entrada, em zero como estava no exemplo anterior. Logo em seguida, estimaremos a regressão em dois estágios da seguinte maneira:

\[\hat{tutoring} = \gamma_0 +\gamma_1 Entranceexam_(centralizado) + \gamma_2 Abaixo de 70\% \]

\[Y_{exitexam} = \beta_0 +\beta_1 Entranceexam_(centralizado) +\beta_2 \hat{tutoring}\]

Assim, usaremos os valores preditos da monitoria como variável de tratamento \(D\) no segundo estágio da equação de regressão.

Code
tutoring_centered <- tutoring %>%
  mutate(entrance_centered = entrance_exam - 70,
         below_cutoff = entrance_exam <= 70)

model_fuzzy <- iv_robust(
  exit_exam ~ entrance_centered + tutoring | entrance_centered + below_cutoff,
  data = filter(tutoring_centered, entrance_centered >= -10 & entrance_centered <= 10)
)

model_fuzzy |> tab_model()
  exit exam
Predictors Estimates CI p
(Intercept) 60.14 58.14 – 62.14 <0.001
entrance centered 0.44 0.24 – 0.63 <0.001
tutoringTRUE 9.74 5.98 – 13.50 <0.001
Observations 403
R2 / R2 adjusted 0.365 / 0.361
  • Aqui, o parametro \(tutoringTRUE\) indica o tamanho do efeito, que é de 9,74 pontos no exame final. Caso tentemos estimar o efeito em uma OLS as estimativas estariam enviesadas pois estamos desconsiderando os diferentes grupos e supondo que todos são compliers. Podemos ver a diferença dos modelos na tabela a seguir:
Code
model_sans_instrument <- lm(exit_exam ~ entrance_centered + tutoring,
                            data = filter(tutoring_centered,
                                          entrance_centered >= -10 &
                                            entrance_centered <= 10))

tab_model(model_sans_instrument,model_fuzzy, show.ci = F, dv.labels = c("Modelo sem intrumento", "Modelo com instrumento"))
  Modelo sem intrumento Modelo com instrumento
Predictors Estimates p Estimates p
(Intercept) 59.27 <0.001 60.14 <0.001
entrance centered 0.51 <0.001 0.44 <0.001
tutoringTRUE 11.48 <0.001 9.74 <0.001
Observations 403 403
R2 / R2 adjusted 0.373 / 0.370 0.365 / 0.361
  • Sem o uso de instrumentos, o modelo estima um efeito de quse dois pontos a mais da tutoria. Podemos também estimar modelos não paramétricos para estimar os resultados, do mesmo modo que fizemos com o modelo \(sharp\)
Code
rdrobust(y = tutoring$exit_exam, x = tutoring$entrance_exam,
         c = 70, fuzzy = tutoring$tutoring) %>%
  summary()
Fuzzy RD estimates using local polynomial regression.

Number of Obs.                 1000
BW type                       mserd
Kernel                   Triangular
VCE method                       NN

Number of Obs.                  238          762
Eff. Number of Obs.             170          347
Order est. (p)                    1            1
Order bias  (q)                   2            2
BW est. (h)                  12.985       12.985
BW bias (b)                  19.733       19.733
rho (h/b)                     0.658        0.658
Unique Obs.                     238          762

First-stage estimates.

=============================================================================
        Method     Coef. Std. Err.         z     P>|z|      [ 95% C.I. ]       
=============================================================================
  Conventional    -0.708     0.073    -9.751     0.000    [-0.850 , -0.565]    
        Robust         -         -    -8.424     0.000    [-0.907 , -0.565]    
=============================================================================

Treatment effect estimates.

=============================================================================
        Method     Coef. Std. Err.         z     P>|z|      [ 95% C.I. ]       
=============================================================================
  Conventional     9.683     1.893     5.116     0.000     [5.973 , 13.393]    
        Robust         -         -     4.258     0.000     [5.210 , 14.095]    
=============================================================================

Assim, estimamos um efeito similar a partir de métodos não paramétricos, mantendo a significancia estatística dos resultados.

3 Limitações do método

  • Apesar de ser uma poderosa técnica para inferência causal, a RDD possui algumas limitações que desafiam sua validade interna e externa.

  • Validade interna: Nós assumimos que todos os fatores não observáveis variam de acordo com \(X\), contudo não podemos validar essa premissa por meio de testes estatísticos. Assim, é essencial entender como \(X\) foi determinado a fim de obter estimativas não viesadas.

  • Validade externa: Devido ao desenho para um efeito local, não é possível inferir os resultados para populações fora do entorno do ponto de corte.

  • Recomendações para a implementação de uma RDD:

    1. Mostrar a distribuição de variáveis de confusão em função de \(X\)
    1. Apresente os principais gr·Öcos de RD usando médias locais
    1. Caso use uma especificação polinomial, faça o gráfico
    1. Mostre sensibilidade dos resultados a diversas escolhas de \(h\) (bandwidth) na ordem do polinômio escolhido
    1. Conduza um RD em paralelo para as covariadas
    1. Mostre a sensibilidade dos resultados em relação a introdução de variáveis controle.

4 Referências

Angrist, Joshua and Jörn-Steffen Pischke. 2014. Mastering ’Metrics: The Path from Cause to Effect. Princeton University Test

Carpenter, Christopher and Carlos Dobkin.2011. The Minimum Legal Drinking Age and Public Health JOURNAL OF ECONOMIC PERSPECTIVES 25(2)

Munzert, Simon. 2021. “Regression Discontinuity Designs” Statistical Modeling and Causal Inference