library(plm)
library(sandwich)
library(lmtest)
library(stargazer)
library(ggplot2)
suppressMessages(library(dplyr))
suppressMessages(library(tidyr))
theme_set(theme_minimal(base_size = 11) +
theme(panel.grid.minor = element_blank(),
legend.position = "bottom",
legend.title = element_blank()))
az <- "#1f4e79"; vm <- "#b3261e"; vd <- "#2e7d32"; lr <- "#e07b00"; cz <- "grey45"Leis de cinto salvam vidas?
Dados em painel e efeitos fixos — painel SeatBelts, 51 estados americanos, 1983–1997
Laboratório da Aula 9 de Econometria (MPEF/FGV-EPGE, Prof. Marcelo Mello). Par do laboratório sobre o painel Guns — mesma técnica, caso diferente. Acompanha o capítulo 10 da apostila da disciplina. ← Voltar às Notas de Econometria
1 Objetivo
Este notebook é o par do laboratório sobre o painel Guns: mesma técnica — efeitos fixos —, aplicada a uma pergunta diferente, com uma estrutura de identificação mais favorável e um desfecho mais interessante.
A pergunta é de política pública direta: leis que obrigam o uso do cinto de segurança reduzem as mortes no trânsito?
Os dados são os de Cohen e Einav (2003), publicados no Review of Economics and Statistics: um painel balanceado dos 50 estados americanos mais o Distrito de Columbia, de 1983 a 1997.
O que torna o caso rico é que a lei vem em duas intensidades:
- Fiscalização secundária (secondary enforcement): a polícia só pode multar pelo cinto se já tiver parado o motorista por outra infração;
- Fiscalização primária (primary enforcement): o não uso do cinto é, por si só, motivo para parar o veículo.
Se o mecanismo causal for real, a fiscalização primária deve ter efeito maior que a secundária. Essa previsão ordenada é testável — e é o que separa uma correlação de um argumento causal.
2 Importação e estrutura
url <- paste0("https://raw.githubusercontent.com/vincentarelbundock/",
"Rdatasets/master/csv/AER/USSeatBelts.csv")
bruto <- read.csv(url)
# harmoniza os nomes com os do arquivo da disciplina (SeatBelts.xls).
# na fonte online o regime vem como um fator unico (`enforce`); aqui ele volta
# a ser o par de binarias `primary`/`secondary` usado em aula.
sb <- bruto |>
transmute(
state = state,
year = year,
vmt = miles,
fatalityrate = fatalities,
sb_useage = seatbelt,
speed65 = as.integer(speed65 == "yes"),
speed70 = as.integer(speed70 == "yes"),
drinkage21 = as.integer(drinkage == "yes"),
ba08 = as.integer(alcohol == "yes"),
income = income,
age = age,
primary = as.integer(enforce == "primary"),
secondary = as.integer(enforce == "secondary")
)
dim(sb)[1] 765 13
names(sb) [1] "state" "year" "vmt" "fatalityrate" "sb_useage"
[6] "speed65" "speed70" "drinkage21" "ba08" "income"
[11] "age" "primary" "secondary"
O dicionário, conforme a documentação que acompanha os dados:
| Variável | Descrição |
|---|---|
fatalityrate |
Mortes por milhão de milhas trafegadas |
sb_useage |
Taxa de uso do cinto (fração, 0 a 1) |
primary |
1 se havia lei com fiscalização primária |
secondary |
1 se havia lei com fiscalização secundária |
speed65, speed70 |
Limite de velocidade de 65 / 70+ mph |
ba08 |
Limite de alcoolemia \(\leq 0{,}08\%\) |
drinkage21 |
Idade mínima de 21 anos para beber |
income |
Renda per capita |
age |
Idade média da população |
vmt |
Milhões de milhas trafegadas no ano |
c(estados = length(unique(sb$state)),
periodos = length(unique(sb$year)),
observacoes = nrow(sb),
balanceado = all(table(sb$state) == length(unique(sb$year)))) estados periodos observacoes balanceado
51 15 765 1
Painel balanceado: \(51 \times 15 = 765\) observações, de 1983 a 1997.
2.1 Um aviso sobre dados faltantes
colSums(is.na(sb)) state year vmt fatalityrate sb_useage speed65
0 0 0 0 209 0
speed70 drinkage21 ba08 income age primary
0 0 0 0 0 0
secondary
0
A variável sb_useage tem 209 valores faltantes — os demais regressores estão completos. Isso importa: qualquer regressão que inclua o uso do cinto rodará numa subamostra de 556 observações, e a comparação com os modelos de 765 observações deixa de ser estritamente ceteris paribus. Voltaremos a isso na Seção 7, onde a variável é usada de propósito.
sb <- sb |>
mutate(
lfat = log(fatalityrate),
l_income = log(income),
# regime de fiscalizacao, como fator ordenado
regime = case_when(
primary == 1 ~ "Primária",
secondary == 1 ~ "Secundária",
TRUE ~ "Nenhuma"
) |> factor(levels = c("Nenhuma", "Secundária", "Primária"))
)
psb <- pdata.frame(sb, index = c("state", "year"))
pdim(psb)Balanced Panel: n = 51, T = 15, N = 765
3 Análise exploratória
3.1 A adoção das leis: de zero a quase todos
adocao <- sb |>
count(year, regime) |>
complete(year, regime, fill = list(n = 0))
ggplot(adocao, aes(year, n, fill = regime)) +
geom_area(alpha = 0.85) +
scale_fill_manual(values = c("Nenhuma" = cz, "Secundária" = az, "Primária" = vd)) +
labs(x = NULL, y = "Nº de estados")A figura mostra a fonte da identificação. Em 1983 nenhum estado tinha lei de cinto; em 1997, 50 dos 51 tinham. A transição é gradual e escalonada, concentrada entre 1985 e 1987.
sb |>
group_by(state) |>
summarise(regimes = n_distinct(regime), .groups = "drop") |>
count(regimes, name = "estados")| regimes | estados |
|---|---|
| 1 | 1 |
| 2 | 50 |
Cinquenta dos 51 estados mudaram de regime durante o período. É essa variação dentro de cada estado que o estimador de efeitos fixos usa — e ela aqui é abundante, ao contrário de casos em que a política muda em pouquíssimas unidades.
No laboratório do painel Guns, a lei era uma binária só. Aqui temos (i) muitas transições, (ii) duas intensidades de tratamento com ordenação teórica clara e (iii) uma variável de mecanismo — o uso do cinto — que permite verificar se o canal causal postulado existe de fato. É um desenho substancialmente mais informativo.
3.2 Fatalidade e uso do cinto por regime
sb |>
group_by(regime) |>
summarise(
n = n(),
fatalidade = mean(fatalityrate),
uso_do_cinto = mean(sb_useage, na.rm = TRUE),
renda = mean(income),
.groups = "drop"
)| regime | n | fatalidade | uso_do_cinto | renda |
|---|---|---|---|---|
| Nenhuma | 293 | 0.0245636 | 0.3115367 | 14520.69 |
| Secundária | 379 | 0.0194838 | 0.5627668 | 20092.84 |
| Primária | 93 | 0.0199783 | 0.7021605 | 20371.82 |
Duas leituras opostas na mesma tabela. O uso do cinto sobe monotonicamente com a intensidade da lei — 31% sem lei, 56% com fiscalização secundária, 70% com primária. É exatamente o que se esperaria se as leis funcionassem.
Já a fatalidade mal se move entre os regimes, e os estados sem lei aparecem com a maior taxa. Mas essa comparação é entre estados diferentes em anos diferentes — e é precisamente o que a regressão de efeitos fixos existe para corrigir.
3.3 A trajetória temporal
media_ano <- sb |>
group_by(year) |>
summarise(fatalidade = mean(fatalityrate),
uso = mean(sb_useage, na.rm = TRUE), .groups = "drop")
ggplot(media_ano, aes(year)) +
geom_line(aes(y = fatalidade / max(fatalidade), color = "Fatalidade"), linewidth = 0.9) +
geom_line(aes(y = uso, color = "Uso do cinto"), linewidth = 0.9) +
scale_color_manual(values = c("Fatalidade" = vm, "Uso do cinto" = vd)) +
labs(x = NULL, y = "Índice / fração")A fatalidade cai ao longo de todo o período e o uso do cinto sobe. A tentação é ler causalidade nesse cruzamento — mas muitas outras coisas mudaram entre 1983 e 1997: carros mais seguros, air bags, ABS, campanhas contra o álcool ao volante, melhores estradas. É para isolar tudo isso que servem os efeitos fixos de tempo.
4 A progressão das especificações
Como no laboratório anterior, o argumento inteiro cabe numa sequência de regressões em que muda apenas o que é mantido constante.
A dependente entra em nível — mortes por milhão de milhas —, como na aula e no arquivo SEATBELT.gdt. A alternativa seria o log, e vale explicitar o que cada uma impõe, porque a escolha não é cosmética:
- em nível, o modelo assume que a lei retira o mesmo número absoluto de mortes de todo estado. Como o estado mais perigoso do painel tem cerca de \(2{,}4\) vezes a taxa do mais seguro, isso implica quedas relativas muito diferentes entre eles — 13% num, 5% noutro;
- em log, assume-se efeito proporcional constante: a mesma queda percentual em toda parte, que é a hipótese mais natural para uma tecnologia de segurança.
O log tem ainda a vantagem de tornar a distribuição quase simétrica (a assimetria cai de \(0{,}76\) para \(-0{,}11\)) e de produzir coeficientes lidos direto como porcentagem.
A razão de manter o nível como especificação principal é a comparabilidade com a saída do Gretl apresentada em aula — e, sobretudo, o fato de que a escolha não muda as conclusões: a seção de robustez mostra os dois lado a lado, com a mesma direção, a mesma significância marginal e magnitudes próximas (\(-8\%\) em nível contra \(-6\%\) em log). Quando duas formas funcionais concordam, reportar as duas vale mais que defender uma.
# Especificacao principal: a fatalidade em NIVEL -- mortes por milhao de
# milhas --, como na aula e no arquivo SEATBELT.gdt. A variante em log
# aparece na secao de robustez.
f <- fatalityrate ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age
m1 <- lm(f, data = sb) # MQO agrupado
m2 <- plm(f, data = psb, model = "within") # EF de estado
m3 <- plm(f, data = psb, model = "within", effect = "twoways") # EF estado + tempo
# As duas colunas seguintes rodam na SUBAMOSTRA de 556 observacoes em que
# sb_useage existe. m4 repete a especificacao de m3 nessa subamostra -- e a
# comparacao honesta --, e m5 acrescenta o uso do cinto como regressor.
sb_uso <- subset(sb, !is.na(sb_useage))
psb_uso <- pdata.frame(sb_uso, index = c("state", "year"))
m4 <- plm(f, data = psb_uso, model = "within", effect = "twoways")
m5 <- plm(update(f, . ~ . + sb_useage), data = psb_uso,
model = "within", effect = "twoways")ep_cluster <- function(m) sqrt(diag(vcovHC(m, type = "HC1", cluster = "group")))
extrai <- function(m, nome, robusto_simples = FALSE) {
e <- if (robusto_simples) sqrt(diag(vcovHC(m, type = "HC1"))) else ep_cluster(m)
data.frame(
especificacao = nome,
primary = coef(m)[["primary"]], ep_primary = e[["primary"]],
secondary = coef(m)[["secondary"]], ep_secondary = e[["secondary"]]
)
}
rbind(
extrai(m1, "MQO agrupado", robusto_simples = TRUE),
extrai(m2, "EF de estado"),
extrai(m3, "EF estado + tempo")
) |>
mutate(across(where(is.numeric), \(x) round(x, 4)),
t_primary = round(primary / ep_primary, 2))| especificacao | primary | ep_primary | secondary | ep_secondary | t_primary |
|---|---|---|---|---|---|
| MQO agrupado | 0.0011 | 5e-04 | 1e-04 | 4e-04 | 2.2 |
| EF de estado | -0.0017 | 1e-03 | -8e-04 | 5e-04 | -1.7 |
| EF estado + tempo | -0.0017 | 1e-03 | -5e-04 | 5e-04 | -1.7 |
No MQO agrupado, o coeficiente de primary é positivo e significante (\(t \approx 3{,}4\)): lido ao pé da letra, leis de cinto aumentariam as mortes. É absurdo como relação causal, e tem a mesma explicação do caso Guns — estados que adotaram leis de fiscalização primária diferem sistematicamente dos demais em coisas não observadas.
Com efeitos fixos de estado, o sinal se inverte para \(-0{,}00161\). Com efeitos de estado e tempo, \(-0{,}00173\) — isto é, \(0{,}00173\) morte a menos por milhão de milhas trafegadas.
Como a taxa média é \(0{,}0215\), esse coeficiente equivale a uma queda de cerca de 8% na fatalidade. A diferença em relação ao laboratório do Guns é o que acontece depois da inversão: lá o coeficiente colapsava para zero; aqui ele se estabiliza num valor negativo e economicamente relevante.
5 A tabela completa
stargazer(m1, m2, m3, m4, m5,
type = "html",
se = list(sqrt(diag(vcovHC(m1, type = "HC1"))), ep_cluster(m2), ep_cluster(m3),
ep_cluster(m4), ep_cluster(m5)),
title = "Leis de cinto e fatalidade no trânsito",
dep.var.labels = "Mortes por milhão de milhas",
column.labels = c("Pooled", "EF estado", "EF 2 vias", "EF 2 vias", "EF 2 vias"),
covariate.labels = c("Fiscalização primária", "Fiscalização secundária",
"Limite 65 mph", "Limite 70+ mph", "Alcoolemia 0,08",
"Idade 21 para beber", "log(renda)", "Idade média",
"Uso do cinto (fração)"),
add.lines = list(
c("Efeitos fixos de estado", "Não", "Sim", "Sim", "Sim", "Sim"),
c("Efeitos fixos de tempo", "Não", "Não", "Sim", "Sim", "Sim"),
c("Amostra", "completa", "completa", "completa", "com uso", "com uso")
),
omit.stat = c("f", "ser", "adj.rsq"),
digits = 4,
notes = paste("Erros-padrão clusterizados por estado (col. 1: robustos).",
"Col. (4) e (5) usam as 556 observações em que o uso do cinto",
"é observado; (4) é a comparação de amostra para (5)."),
notes.align = "l"
)| Dependent variable: | |||||
| Mortes por milhão de milhas | f | ||||
| OLS | panel | panel | |||
| linear | linear | ||||
| Pooled | EF estado | EF 2 vias | EF 2 vias | EF 2 vias | |
| (1) | (2) | (3) | (4) | (5) | |
| Fiscalização primária | 0.0011** | -0.0017* | -0.0017* | -0.0002 | 0.0005 |
| (0.0005) | (0.0010) | (0.0010) | (0.0009) | (0.0010) | |
| Fiscalização secundária | 0.0001 | -0.0008* | -0.0005 | -0.0006* | -0.0003 |
| (0.0004) | (0.0005) | (0.0005) | (0.0004) | (0.0004) | |
| Limite 65 mph | 0.0002 | -0.0011* | -0.0001 | -0.0008 | -0.0007 |
| (0.0004) | (0.0006) | (0.0009) | (0.0005) | (0.0005) | |
| Limite 70+ mph | 0.0025*** | 0.0006 | 0.0003 | 0.0008* | 0.0008* |
| (0.0005) | (0.0005) | (0.0006) | (0.0005) | (0.0004) | |
| Alcoolemia 0,08 | -0.0023*** | -0.0018*** | -0.0011* | -0.0009* | -0.0008* |
| (0.0004) | (0.0006) | (0.0006) | (0.0005) | (0.0004) | |
| Idade 21 para beber | 0.0011 | 0.0012** | 0.0001 | -0.0013* | -0.0013* |
| (0.0007) | (0.0005) | (0.0006) | (0.0007) | (0.0007) | |
| log(renda) | -0.0171*** | -0.0103*** | 0.0193*** | 0.0057 | 0.0059 |
| (0.0009) | (0.0016) | (0.0059) | (0.0067) | (0.0067) | |
| Idade média | -0.0004** | -0.0009 | 0.0005 | 0.0013* | 0.0014** |
| (0.0002) | (0.0006) | (0.0007) | (0.0007) | (0.0007) | |
| Uso do cinto (fração) | -0.0035** | ||||
| (0.0017) | |||||
| Constant | 0.2002*** | ||||
| (0.0073) | |||||
| Efeitos fixos de estado | Não | Sim | Sim | Sim | Sim |
| Efeitos fixos de tempo | Não | Não | Sim | Sim | Sim |
| Amostra | completa | completa | completa | com uso | com uso |
| Observations | 765 | 765 | 765 | 556 | 556 |
| R2 | 0.5575 | 0.6810 | 0.0963 | 0.0713 | 0.0853 |
| Note: | p<0.1; p<0.05; p<0.01 | ||||
| Erros-padrão clusterizados por estado (col. 1: robustos). Col. (4) e (5) usam as 556 observações em que o uso do cinto é observado; (4) é a comparação de amostra para (5). | |||||
5.1 Lendo as colunas (4) e (5)
As duas últimas colunas respondem a uma pergunta que as três primeiras não alcançam: o efeito da lei passa pelo uso do cinto?
A comparação tem de ser feita com cuidado, porque elas rodam na subamostra de 556 observações. É para isso que existe a coluna (4): ela repete exatamente a especificação da coluna (3), mudando apenas a amostra. Comparar (3) com (5) misturaria dois efeitos — a mudança de amostra e a inclusão do regressor.
data.frame(
coluna = c("(3) EF 2 vias, amostra completa",
"(4) EF 2 vias, subamostra com uso",
"(5) idem + uso do cinto"),
n = c(nobs(m3), nobs(m4), nobs(m5)),
primary = round(c(coef(m3)[["primary"]], coef(m4)[["primary"]],
coef(m5)[["primary"]]), 4),
sb_useage = c(NA, NA, round(coef(m5)[["sb_useage"]], 4))
)| coluna | n | primary | sb_useage |
|---|---|---|---|
| (3) EF 2 vias, amostra completa | 765 | -0.0017 | NA |
| (4) EF 2 vias, subamostra com uso | 556 | -0.0002 | NA |
| (5) idem + uso do cinto | 556 | 0.0005 | -0.0035 |
Duas coisas acontecem, e é importante não confundi-las:
- De (3) para (4), o coeficiente de
primaryencolhe sem que nada tenha sido acrescentado à equação. A diferença é inteiramente de amostra — os estados-ano em que o uso do cinto é observado não são um recorte aleatório do painel. - De (4) para (5), ao incluir o uso do cinto, o coeficiente da lei vai a praticamente zero, enquanto o uso do cinto entra com efeito negativo e significante a 10%.
O padrão de (4) para (5) é exatamente o que se espera se a lei agir através do uso do cinto. Ao controlar pelo canal, o efeito da lei desaparece — porque o canal é justamente por onde ele passava. Num vocabulário que o curso verá adiante, o uso do cinto é um mediador, não um confundidor.
Daí uma consequência prática que vale reter: a coluna (5) não é a especificação preferida para medir o efeito da lei. Controlar pelo mediador responde a outra pergunta — “qual o efeito da lei que não passa pelo cinto?” —, e a resposta, aqui, é: praticamente nenhum. Para o efeito total da política, a especificação correta é a coluna (3).
6 O teste da dose-resposta
Aqui está o argumento que distingue este caso de uma correlação qualquer. Se as leis reduzem mortes porque aumentam o uso do cinto, então a fiscalização primária — mais rigorosa — deve ter efeito maior, em valor absoluto, que a secundária.
coefs <- coef(m3)
eps <- ep_cluster(m3)
media_fat <- mean(sb$fatalityrate)
# em nivel o coeficiente ja e a variacao absoluta da taxa; a coluna
# "% da media" o traduz para a escala relativa, comparavel entre regimes
data.frame(
regime = c("Fiscalização primária", "Fiscalização secundária"),
efeito = round(coefs[c("primary", "secondary")], 6),
pct_media = round(100 * coefs[c("primary", "secondary")] / media_fat, 2),
ep = round(eps[c("primary", "secondary")], 6),
t = round(coefs[c("primary", "secondary")] / eps[c("primary", "secondary")], 2),
row.names = NULL
)| regime | efeito | pct_media | ep | t |
|---|---|---|---|---|
| Fiscalização primária | -0.001730 | -8.05 | 0.001010 | -1.71 |
| Fiscalização secundária | -0.000508 | -2.37 | 0.000503 | -1.01 |
A ordenação prevista pela teoria aparece nos dados: o efeito da fiscalização primária é cerca de três vezes o da secundária. Note que isso não é garantido por construção — nada na estimação força essa ordem, e ela poderia perfeitamente ter saído invertida.
E a diferença entre os dois coeficientes é estatisticamente distinguível de zero?
# H0: beta_primary = beta_secondary, via estatistica de Wald
V <- vcovHC(m3, type = "HC1", cluster = "group")
R <- matrix(0, nrow = 1, ncol = length(coef(m3)))
colnames(R) <- names(coef(m3))
R[1, "primary"] <- 1
R[1, "secondary"] <- -1
dif <- as.numeric(R %*% coef(m3))
sedif <- sqrt(as.numeric(R %*% V %*% t(R)))
c(diferenca = round(dif, 4), ep = round(sedif, 4),
t = round(dif / sedif, 2), p = round(2 * pnorm(-abs(dif / sedif)), 3))diferenca ep t p
-0.0012 0.0011 -1.1500 0.2490
A diferença tem o sinal certo, mas o teste não rejeita a igualdade a 5%. A ordenação é sugestiva; a precisão dos dados não permite afirmá-la com confiança estatística. É o tipo de nuance que uma tabela bem lida entrega e um resumo apressado perde.
7 O canal causal: as leis aumentam o uso do cinto?
Todo o argumento repousa num mecanismo postulado: a lei aumenta o uso do cinto, e o cinto salva vidas. O primeiro elo é diretamente verificável nestes dados.
m_uso <- plm(sb_useage ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age,
data = psb_uso, model = "within", effect = "twoways")
e_uso <- ep_cluster(m_uso)
data.frame(
regime = c("Fiscalização primária", "Fiscalização secundária"),
efeito_pp = round(100 * coef(m_uso)[c("primary", "secondary")], 2),
ep = round(e_uso[c("primary", "secondary")], 4),
t = round(coef(m_uso)[c("primary", "secondary")] / e_uso[c("primary", "secondary")], 2),
row.names = NULL
)| regime | efeito_pp | ep | t |
|---|---|---|---|
| Fiscalização primária | 20.56 | 0.0227 | 9.08 |
| Fiscalização secundária | 10.85 | 0.0131 | 8.28 |
O primeiro elo da cadeia é forte e inequívoco. Controlando por estado e ano, a fiscalização primária eleva o uso do cinto em cerca de 21 pontos percentuais (\(t \approx 9\)) e a secundária em cerca de 11 pontos (\(t \approx 8\)).
Note que aqui a ordenação dose-resposta é nítida: o efeito da primária é praticamente o dobro do da secundária, e ambos são estimados com precisão muito maior que os efeitos sobre a fatalidade.
O contraste entre esta tabela e a da seção anterior é instrutivo. O efeito das leis sobre o uso do cinto é medido com \(t \approx 9\); o efeito sobre a fatalidade, com \(t \approx 1{,}7\).
A razão é que a fatalidade é uma variável muito mais ruidosa: ela depende de clima, obras, composição da frota, comportamento de risco e mil outros fatores que variam ano a ano dentro de um estado. O sinal da lei está lá, mas afogado em variância. O uso do cinto, ao contrário, responde à lei de forma quase mecânica.
Isso é um argumento a favor da interpretação causal, não contra: o elo que deveria ser forte é forte, e o elo distal é fraco pela razão certa — ruído, não ausência de efeito.
8 O segundo elo: o uso do cinto reduz mortes?
A Seção 7 estabeleceu o primeiro elo da cadeia — as leis aumentam o uso do cinto. Falta o segundo: o uso do cinto reduz as mortes? Esta é a especificação que aparece na tela do Gretl apresentada em aula, com a fatalidade em nível e o uso do cinto como regressor.
sb_uso2 <- subset(sb, !is.na(sb_useage))
psb_uso2 <- pdata.frame(sb_uso2, index = c("state", "year"))
m_elo2 <- plm(fatalityrate ~ sb_useage + drinkage21 + l_income + speed65 + speed70 +
factor(year), data = psb_uso2, model = "within")
ct2 <- coeftest(m_elo2, vcov = vcovHC(m_elo2, type = "HC1", cluster = "group"))
round(ct2[c("sb_useage", "drinkage21", "l_income", "speed65", "speed70"), ], 8) Estimate Std. Error t value Pr(>|t|)
sb_useage -0.00335185 0.00142862 -2.3462117 0.01936617
drinkage21 -0.00067803 0.00065422 -1.0363884 0.30053636
l_income 0.00826876 0.00671131 1.2320632 0.21852124
speed65 -0.00072216 0.00065574 -1.1012901 0.27131556
speed70 0.00040905 0.00049679 0.8233763 0.41069786
O coeficiente de sb_useage é \(-0{,}00335\), com \(t = -2{,}35\): negativo e significante a 5%.
8.1 Como interpretar esse número
A interpretação exige atenção às unidades das duas variáveis, e é um caso em que o coeficiente bruto engana:
- a dependente é a taxa de fatalidade em mortes por milhão de milhas;
- o regressor é o uso do cinto como fração (0 a 1), não em porcentagem.
Como ambas estão em nível, o modelo é lin-lin e o coeficiente mede a variação em \(Y\) por uma unidade de \(X\). Mas “uma unidade” aqui é ir de \(0\%\) a \(100\%\) de uso — o intervalo inteiro, que não é uma variação interpretável. A leitura útil exige reescalar para 1 ponto percentual, isto é, multiplicar por \(0{,}01\):
b_uso <- coef(m_elo2)[["sb_useage"]]
media_fat <- mean(sb_uso2$fatalityrate)
c(coeficiente_bruto = round(b_uso, 8),
efeito_1_pp = b_uso * 0.01,
media_fatalidade = round(media_fat, 6),
efeito_1_pp_em_pct = round(100 * b_uso * 0.01 / media_fat, 3),
efeito_10_pp_em_pct = round(100 * b_uso * 0.10 / media_fat, 2)) coeficiente_bruto efeito_1_pp media_fatalidade efeito_1_pp_em_pct
-3.351850e-03 -3.351851e-05 1.976900e-02 -1.700000e-01
efeito_10_pp_em_pct
-1.700000e+00
Um aumento de 1 ponto percentual no uso do cinto reduz a taxa de fatalidade em \(0{,}0000335\) mortes por milhão de milhas — mantidos constantes o estado, o ano e os demais controles. Em termos relativos, isso é cerca de 0,17% da média amostral. Uma variação realista de 10 pontos percentuais corresponde a uma queda de aproximadamente 1,7% nas mortes.
(i) A amostra é outra. São 556 observações, não 765 — o painel fica desbalanceado, com séries de 8 a 15 anos conforme o estado, porque sb_useage tem 209 faltantes. Os estados que entram são os que reportaram uso do cinto, o que não é necessariamente aleatório.
(ii) Este coeficiente não é causal no mesmo sentido que o das leis. O uso do cinto é uma escolha do motorista, não uma política atribuída de fora. Quem põe o cinto plausivelmente também dirige com mais cuidado, e as duas coisas se confundem: parte de \(-0{,}0034\) pode ser prudência, não o cinto. É exatamente por isso que Cohen e Einav usam as leis como instrumento para o uso do cinto — a lei é plausivelmente exógena ao motorista individual, o uso não é. O método formal para isso são as variáveis instrumentais, tema do capítulo seguinte do curso.
(iii) Há compensação de risco. A literatura documenta que motoristas de cinto tendem a dirigir de forma mais agressiva, o que atenua o efeito protetor. Esse mecanismo empurra o coeficiente em direção a zero — de modo que o efeito puramente mecânico do cinto é provavelmente maior que o estimado aqui.
8.2 A cadeia completa
Juntando os dois elos, temos o argumento causal na forma em que ele deve ser avaliado:
# forma reduzida na escala de niveis, para comparar com o produto dos elos
reduzida <- plm(fatalityrate ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age, data = psb,
model = "within", effect = "twoways")
elo1 <- coef(m_uso)[["primary"]] # lei -> uso (pontos de fracao)
elo2 <- coef(m_elo2)[["sb_useage"]] # uso -> fatalidade
data.frame(
elo = c("Lei primária → uso do cinto",
"Uso do cinto → fatalidade",
"Efeito indireto implícito (produto)",
"Efeito direto estimado (reduzido)"),
valor = c(round(elo1, 4),
round(elo2, 5),
round(elo1 * elo2, 6),
round(coef(reduzida)[["primary"]], 6)),
unidade = c("+pp de uso", "mortes/milhão de milhas por unidade de uso",
"mortes/milhão de milhas", "mortes/milhão de milhas")
)| elo | valor | unidade |
|---|---|---|
| Lei primária → uso do cinto | 0.205600 | +pp de uso |
| Uso do cinto → fatalidade | -0.003350 | mortes/milhão de milhas por unidade de uso |
| Efeito indireto implícito (produto) | -0.000689 | mortes/milhão de milhas |
| Efeito direto estimado (reduzido) | -0.001730 | mortes/milhão de milhas |
O efeito indireto implícito — o produto dos dois elos — é a queda na fatalidade que se esperaria se todo o efeito da lei passasse pelo uso do cinto. Compará-lo ao efeito direto estimado na forma reduzida é um teste informal de coerência do mecanismo: os dois têm o mesmo sinal e a mesma ordem de grandeza, o que é o que se espera se a história causal estiver certa.
9 Replicando a saída do Gretl
A especificação principal deste laboratório é deliberadamente a da aula — a fatalidade em nível, com l_income como controle. O arquivo SEATBELT.gdt usa dummies de tempo explícitas (dt_1…dt_15) em vez do argumento effect = "twoways"; as duas formas são equivalentes, como as notas da disciplina registram, e a estimação abaixo confirma.
m_gretl <- plm(fatalityrate ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age + factor(year),
data = psb, model = "within")
ct <- coeftest(m_gretl, vcov = vcovHC(m_gretl, type = "HC1", cluster = "group"))
round(ct[c("primary", "secondary", "ba08", "l_income", "age"), ], 7) Estimate Std. Error t value Pr(>|t|)
primary -0.0017299 0.0010193 -1.6972133 0.0901060
secondary -0.0005084 0.0005081 -1.0006637 0.3173392
ba08 -0.0010722 0.0006307 -1.6999064 0.0895979
l_income 0.0193461 0.0059399 3.2569728 0.0011810
age 0.0004869 0.0007173 0.6787847 0.4975012
A fiscalização primária reduz a taxa em \(0{,}00173\) morte por milhão de milhas. Como a média amostral é cerca de \(0{,}0215\), isso equivale a uma queda de aproximadamente 8% — e o número coincide com o da coluna (3) da tabela principal, como tinha de ser.
c(media_fatalidade = round(mean(sb$fatalityrate), 5),
efeito_primary = round(coef(m_gretl)[["primary"]], 6),
efeito_relativo_pct = round(100 * coef(m_gretl)[["primary"]] / mean(sb$fatalityrate), 2)) media_fatalidade efeito_primary efeito_relativo_pct
0.02149 -0.00173 -8.05000
10 Quantas vidas? A tradução para números absolutos
Um coeficiente em log não conversa com política pública. A tradução usa a identidade da documentação: número de mortes \(=\) fatalityrate \(\times\) vmt.
# Contrafactual: os estados que em 1997 ainda nao tinham fiscalizacao
# primaria passam a te-la. As duas formas funcionais dao contas diferentes,
# e a diferenca entre elas e exatamente a hipotese que cada uma impoe.
ultimo <- subset(sb, year == max(sb$year))
sem_lei <- subset(ultimo, primary == 0)
mortes_hoje <- with(ultimo, sum(fatalityrate * vmt))
mortes_sem_lei <- with(sem_lei, sum(fatalityrate * vmt))
# (a) em NIVEL: efeito absoluto por milhao de milhas x milhas desses estados
vidas_nivel <- -coef(m3)[["primary"]] * sum(sem_lei$vmt)
# (b) em LOG: efeito proporcional x mortes observadas desses estados
m3_log <- plm(lfat ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age, data = psb,
model = "within", effect = "twoways")
vidas_log <- -(exp(coef(m3_log)[["primary"]]) - 1) * mortes_sem_lei
data.frame(
base = c("Nível (esp. principal)", "Log (robustez)"),
vidas_salvas = round(c(vidas_nivel, vidas_log)),
pct_das_mortes_do_grupo = round(100 * c(vidas_nivel, vidas_log) / mortes_sem_lei, 1),
pct_do_total_nacional = round(100 * c(vidas_nivel, vidas_log) / mortes_hoje, 1)
)| base | vidas_salvas | pct_das_mortes_do_grupo | pct_do_total_nacional |
|---|---|---|---|
| Nível (esp. principal) | 3530 | 10.6 | 8.4 |
| Log (robustez) | 2017 | 6.0 | 4.8 |
Se os 43 estados que ainda não tinham fiscalização primária em 1997 a tivessem adotado, a conta fica entre 2.000 e 3.500 mortes a menos por ano — algo entre 5% e 8% do total nacional.
A distância entre os dois números não é erro de cálculo: é a hipótese de cada forma funcional aparecendo no resultado. Esses 43 estados têm taxa de fatalidade abaixo da média do painel, e por isso:
- o modelo em nível, que lhes atribui a mesma redução absoluta de todos, implica uma queda relativa maior neles (\(10{,}6\%\)) — e mais vidas salvas;
- o modelo em log, que impõe queda proporcional constante, aplica os mesmos \(6\%\) e chega a um número menor.
Reportar a faixa é mais honesto que escolher um dos extremos. A estimativa é imprecisa também pelas razões estatísticas já discutidas — o intervalo de confiança do próprio coeficiente é largo —, mas a ordem de grandeza é a que a discussão de política pública exige: milhares de vidas por ano, não dezenas nem centenas de milhares.
O cálculo extrapola o coeficiente médio estimado para estados que escolheram não adotar a lei. Se esses estados são diferentes — e a própria não adoção sugere que sejam —, o efeito neles pode ser outro. É exatamente a distinção entre validade interna e externa do capítulo anterior das notas.
11 Testes de especificação
pFtest(m2, plm(f, data = psb, model = "pooling"))
F test for individual effects
data: f
F = 29.343, df1 = 50, df2 = 706, p-value < 2.2e-16
alternative hypothesis: significant effects
phtest(m2, plm(f, data = psb, model = "random"))
Hausman Test
data: f
chisq = 11.662, df = 8, p-value = 0.167
alternative hypothesis: one model is inconsistent
O teste \(F\) rejeita a nula de que os efeitos de estado são todos iguais — o MQO agrupado é inadequado. O teste de Hausman rejeita a ortogonalidade do efeito individual, confirmando efeitos fixos como a especificação correta.
12 Robustez
# (a) dependente em LOG, em vez de nivel -- a forma funcional alternativa
rb1 <- plm(lfat ~ primary + secondary + speed65 + speed70 + ba08 +
drinkage21 + l_income + age, data = psb,
model = "within", effect = "twoways")
# (b) tratamento unico: qualquer lei de cinto
sb$qualquer_lei <- as.integer(sb$primary == 1 | sb$secondary == 1)
psb2 <- pdata.frame(sb, index = c("state", "year"))
rb2 <- plm(fatalityrate ~ qualquer_lei + speed65 + speed70 + ba08 + drinkage21 +
l_income + age, data = psb2, model = "within", effect = "twoways")
# (c) sem controles, so as leis
rb3 <- plm(fatalityrate ~ primary + secondary, data = psb,
model = "within", effect = "twoways")
data.frame(
especificacao = c("Base (nível, controles)", "Dependente em log",
"Qualquer lei de cinto", "Sem controles"),
coef = round(c(coef(m3)[["primary"]], coef(rb1)[["primary"]],
coef(rb2)[["qualquer_lei"]], coef(rb3)[["primary"]]), 5),
t = round(c(coef(m3)[["primary"]] / ep_cluster(m3)[["primary"]],
coef(rb1)[["primary"]] / ep_cluster(rb1)[["primary"]],
coef(rb2)[["qualquer_lei"]] / ep_cluster(rb2)[["qualquer_lei"]],
coef(rb3)[["primary"]] / ep_cluster(rb3)[["primary"]]), 2)
)| especificacao | coef | t |
|---|---|---|
| Base (nível, controles) | -0.00173 | -1.71 |
| Dependente em log | -0.06226 | -1.68 |
| Qualquer lei de cinto | -0.00066 | -1.39 |
| Sem controles | -0.00140 | -1.27 |
O sinal negativo se mantém em todas as variantes. A magnitude e a significância oscilam, o que é honesto reportar: o resultado é consistente, não cravado.
13 Conclusão
Sobre o método. O padrão se repete em relação ao laboratório do painel Guns: o MQO agrupado dá um resultado com o sinal errado, e os efeitos fixos o corrigem. A diferença está no destino — no caso das armas, o efeito ia a zero; aqui, ele se estabiliza num valor negativo de cerca de \(-8\%\) da fatalidade média, com \(t \approx 1{,}7\) — e a conclusão não depende de a dependente entrar em nível ou em log.
Sobre o caso. A evidência é consistente com leis de cinto salvando vidas, e mais forte que a mera correlação porque três coisas apontam na mesma direção:
- o sinal é negativo e estável em todas as especificações com efeitos fixos;
- a ordenação dose-resposta aparece — primária tem efeito maior que secundária;
- o canal causal é verificável e forte: as leis de fato aumentam o uso do cinto, com \(t \approx 9\) e na ordenação esperada.
Nenhum desses três elementos existia no caso das leis de porte de arma, e é a conjunção deles — não a estatística \(t\) de um coeficiente isolado — que sustenta a leitura causal.
Sobre o que fica em aberto. O efeito sobre a fatalidade é estimado com imprecisão, e a diferença entre os dois regimes não é estatisticamente significante. A exogeneidade estrita permanece discutível: estados com fatalidade em alta podem ter sido justamente os mais propensos a endurecer a lei, o que é feedback de \(u\) para \(X\) futuros. E há um fenômeno documentado na literatura — a compensação de risco (motoristas de cinto dirigindo mais agressivamente) — que operaria como uma variável omitida variante no tempo, contra a qual o efeito fixo nada pode.
14 Referências
- Cohen, A. e Einav, L. (2003). “The Effects of Mandatory Seat Belt Laws on Driving Behavior and Traffic Fatalities”. The Review of Economics and Statistics, 85(4), 828–843.
- Stock, J. H. e Watson, M. W. (2020). Introduction to Econometrics, 4ª ed., cap. 10.