A aviação é um dos meios de transporte mais seguros que existem, e essa segurança vem de um trabalho constante de investigação de ocorrências aeronáuticas. No Brasil, quem coordena esse trabalho é o CENIPA (Centro de Investigação e Prevenção de Acidentes Aeronáuticos), responsável por registrar e investigar os acidentes, incidentes graves e incidentes da aviação civil.
Este projeto tenta entender onde, quando e por que essas ocorrências acontecem. Quais fases do voo concentram mais acidentes? Quais estados registram mais casos? Que fatores humanos e operacionais aparecem com mais frequência? E qual é o grau de letalidade de cada tipo de ocorrência? São perguntas que interessam tanto a quem estuda ciência de dados e quer praticar com uma base real e bagunçada quanto a quem se preocupa com segurança de voo, já que entender o padrão dos acidentes é o primeiro passo para evitá-los.
A análise usa os dados públicos de Ocorrências Aeronáuticas da Aviação Civil Brasileira, publicados pelo CENIPA no portal dados.gov.br. O conjunto vem em quatro arquivos CSV separados, ligados entre si por códigos de ocorrência:
ocorrencia.csv: a tabela central, uma linha por
ocorrência;aeronave.csv: dados das aeronaves envolvidas;ocorrencia_tipo.csv: o tipo (ou tipos) de cada
ocorrência;fator_contribuinte.csv: os fatores que contribuíram,
quando houve investigação.A metodologia seguiu estas etapas:
;);A ideia foi ir do geral para o específico. Primeiro um panorama, comparando as três classificações de ocorrência e medindo a letalidade de cada uma. Depois o porquê dos eventos mais graves, olhando os fatores contribuintes. Em seguida, o momento do voo em que eles se concentram, a evolução ao longo dos anos, o perfil das aeronaves mais envolvidas e, por fim, a distribuição pelo país. Cada pergunta é respondida com uma tabela ou um gráfico e fechada com um comentário, para o relatório contar uma história em vez de só mostrar números soltos.
O trabalho foi feito em R, usando o tidyverse
(dplyr, tidyr, stringr,
lubridate) para manipular e limpar os dados. O
tidyverse encaixa bem aqui porque há bastante tratamento de
texto, datas e junções, e o encadeamento com %>% deixa
cada transformação explícita e fácil de comentar.
A maior dificuldade é que os dados não vêm prontos. São quatro
tabelas que precisam ser mescladas, com valores ausentes registrados de
formas diferentes (***, NULL, texto vazio) e
algumas relações de um para muitos: uma ocorrência pode ter vários tipos
e vários fatores contribuintes. Por isso a estratégia foi agregar antes
de juntar. As tabelas de um para muitos são primeiro reduzidas a uma
linha por ocorrência (guardando o tipo e o fator principais e criando
contadores) e só depois unidas à tabela central com
left_join. Assim as linhas não se multiplicam à toa. Os
marcadores de ausência viram NA já na leitura, as datas são
padronizadas com o lubridate e o texto em caixa alta é
normalizado com o stringr, para a mesma categoria não
aparecer escrita de duas formas.
Na parte visual, o relatório mistura gráficos estáticos
(ggplot2), gráficos interativos (plotly),
tabelas navegáveis (DT) e um mapa (leaflet),
de modo que o leitor possa explorar os dados por conta própria em vez de
só olhar imagens fixas.
Os resultados interessam a públicos diferentes. Órgãos reguladores como CENIPA e ANAC podem usar os padrões para priorizar campanhas de segurança nas fases de voo e nos fatores mais críticos. Empresas aéreas e escolas de aviação podem direcionar treinamento para os tipos de ocorrência mais comuns nas suas operações. E pesquisadores e jornalistas ganham uma base já organizada para acompanhar a evolução da segurança de voo no Brasil. No fim, a análise transforma quatro arquivos brutos do governo em informação útil sobre segurança aérea.
Os pacotes abaixo são necessários para replicar a análise. Eles
precisam estar instalados antes da execução
(install.packages("nome_do_pacote")).
library(dplyr) # Manipulação e transformação dos dados (filter, mutate, join...)
library(tidyr) # Reformulação de dados (pivot, separate, etc.)
library(stringr) # Limpeza e padronização de texto (maiúsculas, espaços)
library(lubridate) # Conversão e manipulação de datas
library(ggplot2) # Gráficos estáticos baseados na gramática dos gráficos
library(plotly) # Gráficos interativos (hover, zoom)
library(DT) # Tabelas interativas com busca, ordenação e paginação
library(leaflet) # Mapa interativo a partir de latitude/longitude
library(scales) # Formatação de eixos (milhares, porcentagem)
library(knitr) # Geração de tabelas e do relatório
library(kableExtra) # Formatação avançada de tabelas estáticas
Os dados foram obtidos no Portal Brasileiro de Dados Abertos, no conjunto Ocorrências Aeronáuticas da Aviação Civil Brasileira, mantido pelo CENIPA:
https://dados.gov.br/dados/conjuntos-dados/ocorrencias-aeronauticas-da-aviacao-civil-brasileira
Os quatro arquivos (ocorrencia.csv,
aeronave.csv, ocorrencia_tipo.csv e
fator_contribuinte.csv) precisam estar na mesma pasta deste
arquivo .Rmd.
# Os arquivos vêm separados por ";" e em codificação Latin-1 (ISO-8859-1),
# por isso é preciso informar 'sep' e 'fileEncoding' na leitura. Ler como UTF-8
# quebraria os acentos (ex.: o nível de dano "DESTRUÍDA").
ler_cenipa <- function(arquivo) {
read.csv(
arquivo,
sep = ";",
fileEncoding = "latin1",
stringsAsFactors = FALSE,
na.strings = c("", "NULL", "***")
)
}
ocorrencia <- ler_cenipa("ocorrencia.csv")
aeronave <- ler_cenipa("aeronave.csv")
oc_tipo <- ler_cenipa("ocorrencia_tipo.csv")
fator <- ler_cenipa("fator_contribuinte.csv")
# Dimensões de cada tabela original
dim_orig <- tibble::tibble(
Tabela = c("ocorrencia", "aeronave", "ocorrencia_tipo", "fator_contribuinte"),
Linhas = c(nrow(ocorrencia), nrow(aeronave), nrow(oc_tipo), nrow(fator)),
Colunas = c(ncol(ocorrencia), ncol(aeronave), ncol(oc_tipo), ncol(fator))
)
dim_orig
## # A tibble: 4 × 3
## Tabela Linhas Colunas
## <chr> <int> <int>
## 1 ocorrencia 14626 22
## 2 aeronave 14822 20
## 3 ocorrencia_tipo 15432 3
## 4 fator_contribuinte 9106 5
A base é mantida pelo CENIPA e reúne as ocorrências da aviação civil brasileira investigadas pelo órgão, com registros que vão de 2007 até 2026 (data da coleta). A finalidade original dos dados é dar transparência e apoiar a prevenção de acidentes: cada ocorrência registrada alimenta as estatísticas oficiais de segurança de voo.
Alguns pontos importantes da fonte:
ocorrencia repete o mesmo código em cinco colunas
(codigo_ocorrencia, codigo_ocorrencia1 a
codigo_ocorrencia4), e cada uma serve de chave para uma das
outras tabelas.***,
NULL ou texto vazio, e por isso já são convertidos em
NA na leitura.ocorrencia_tipo tem mais linhas que
ocorrencia) e vários fatores contribuintes. Além disso, só
parte das ocorrências (em geral os acidentes) tem fatores investigados,
então essa tabela cobre menos casos.dd/mm/aaaa, números, texto e coordenadas geográficas com
ponto decimal.A preparação tem duas grandes etapas: (a) juntar as quatro tabelas e (b) limpar e enriquecer o resultado.
Etapa (a), junção. A tabela ocorrencia é a espinha
dorsal. A aeronave junta-se quase um para um (a
granularidade do conjunto final passa a ser uma linha por aeronave
envolvida). Já ocorrencia_tipo e
fator_contribuinte têm relação de um para muitos; se fossem
unidas direto, as linhas se multiplicariam. Então essas duas são
agregadas para uma linha por ocorrência antes do join, guardando o tipo
e o fator principais e criando contadores (qtd_tipos,
qtd_fatores).
# Remove as colunas de código redundantes, mantendo só 'codigo_ocorrencia'
ocorrencia <- ocorrencia %>%
select(-codigo_ocorrencia1, -codigo_ocorrencia2,
-codigo_ocorrencia3, -codigo_ocorrencia4)
# Agrega tipos: tipo principal + total de tipos por ocorrência
tipo_agg <- oc_tipo %>%
group_by(codigo_ocorrencia1) %>%
summarise(
ocorrencia_tipo = first(ocorrencia_tipo),
taxonomia_tipo_icao = first(taxonomia_tipo_icao),
qtd_tipos = n(),
.groups = "drop"
)
# Agrega fatores: fator principal (nome/aspecto/área) + total de fatores
fator_agg <- fator %>%
group_by(codigo_ocorrencia3) %>%
summarise(
fator_nome = first(fator_nome),
fator_area = first(fator_area),
fator_aspecto = first(fator_aspecto),
qtd_fatores = n(),
.groups = "drop"
)
# Junção encadeada (left joins a partir da ocorrência)
dados <- ocorrencia %>%
left_join(aeronave, by = c("codigo_ocorrencia" = "codigo_ocorrencia2")) %>%
left_join(tipo_agg, by = c("codigo_ocorrencia" = "codigo_ocorrencia1")) %>%
left_join(fator_agg, by = c("codigo_ocorrencia" = "codigo_ocorrencia3"))
dim(dados) # linhas x colunas do conjunto unido
## [1] 14822 44
Etapa (b), limpeza e enriquecimento. Aqui os tipos são padronizados e são criadas as variáveis derivadas que aparecem na análise. Cada passo abaixo tem um comentário explicando o porquê.
dados_limpos <- dados %>%
mutate(
# Datas: o original vem como texto "dd/mm/aaaa" -> converter para Date real
ocorrencia_dia = dmy(ocorrencia_dia),
# Variável derivada: ano (útil para análise temporal)
ano = year(ocorrencia_dia),
# Converter campos numéricos que vieram como texto
fatalidades = as.integer(aeronave_fatalidades_total),
assentos = as.integer(aeronave_assentos),
ano_fabricacao = as.integer(aeronave_ano_fabricacao),
latitude = as.numeric(ocorrencia_latitude),
longitude = as.numeric(ocorrencia_longitude),
# Padronizar texto em Caixa de Título (evita "EMBRAER" vs "Embraer")
fabricante = str_to_title(str_squish(aeronave_fabricante)),
cidade = str_to_title(str_squish(ocorrencia_cidade)),
# Classificação como fator ordenado por gravidade
classificacao = factor(
ocorrencia_classificacao,
levels = c("INCIDENTE", "INCIDENTE GRAVE", "ACIDENTE")
),
# Nível de dano como fator ordenado
nivel_dano = factor(
aeronave_nivel_dano,
levels = c("NENHUM", "LEVE", "SUBSTANCIAL", "DESTRUÍDA")
),
# Variável derivada: a ocorrência teve ao menos uma fatalidade?
teve_fatalidade = ifelse(!is.na(fatalidades) & fatalidades > 0,
"Com fatalidade", "Sem fatalidade"),
# Faixa de horário (a partir da hora "hh:mm:ss")
hora_num = as.integer(substr(ocorrencia_hora, 1, 2)),
periodo = case_when(
hora_num >= 5 & hora_num < 12 ~ "Manhã",
hora_num >= 12 & hora_num < 18 ~ "Tarde",
hora_num >= 18 & hora_num < 24 ~ "Noite",
TRUE ~ "Madrugada"
)
) %>%
# Mantém apenas registros com data válida e ano dentro do esperado
filter(!is.na(ano), ano >= 2007, ano <= 2026)
dim(dados_limpos)
## [1] 14822 57
Abaixo, uma amostra do conjunto final já limpo (algumas colunas de interesse e as primeiras linhas), em tabela interativa para não imprimir um data frame gigante.
dados_limpos %>%
select(ano, classificacao, ocorrencia_uf, cidade, fabricante,
aeronave_fase_operacao, ocorrencia_tipo, nivel_dano, fatalidades) %>%
head(50) %>%
DT::datatable(
rownames = FALSE,
options = list(pageLength = 10, scrollX = TRUE),
colnames = c("Ano", "Classificação", "UF", "Cidade", "Fabricante",
"Fase do Voo", "Tipo de Ocorrência", "Nível de Dano", "Fatalidades"),
caption = "Amostra (50 primeiras linhas) do conjunto final limpo"
)
A tabela a seguir resume, de forma direta, as principais variáveis usadas na análise exploratória.
| Variável | Tipo | Descrição |
|---|---|---|
| ano | Numérica | Ano da ocorrência (2007 a 2026), derivado da data. |
| classificacao | Fator | Incidente, Incidente Grave ou Acidente (ordem de gravidade). |
| ocorrencia_uf | Texto | Unidade da Federação onde ocorreu. |
| fabricante | Texto | Fabricante da aeronave, padronizado. |
| aeronave_fase_operacao | Texto | Fase do voo (decolagem, cruzeiro, pouso, etc.). |
| ocorrencia_tipo | Texto | Tipo principal da ocorrência (ex.: colisão com ave). |
| fator_nome | Texto | Fator contribuinte principal (quando investigado). |
| fator_area | Fator | Área do fator (humano, operacional, material). |
| nivel_dano | Fator | Dano à aeronave (de nenhum a destruída). |
| fatalidades | Numérica | Total de fatalidades na aeronave. |
| teve_fatalidade | Fator | Indicador derivado: houve ao menos uma morte? |
| periodo | Fator | Faixa do dia (manhã/tarde/noite/madrugada). |
Daqui em diante o relatório segue o roteiro anunciado na introdução, do panorama geral até o detalhe geográfico, com uma pergunta guiando cada subseção.
A primeira pergunta natural é: das três classificações, qual é de fato perigosa? A tabela abaixo cruza a quantidade de registros com o número de mortes e a taxa de fatalidade (proporção de registros com ao menos uma morte).
tab_class <- dados_limpos %>%
group_by(classificacao) %>%
summarise(
registros = n(),
com_morte = sum(teve_fatalidade == "Com fatalidade", na.rm = TRUE),
mortes = sum(fatalidades, na.rm = TRUE),
.groups = "drop"
) %>%
mutate(taxa_fatalidade = round(com_morte / registros * 100, 1)) %>%
arrange(classificacao)
tab_class %>%
kable(
caption = "Tabela 2: Registros, mortes e taxa de fatalidade por classificação",
col.names = c("Classificação", "Registros", "Com fatalidade",
"Total de mortes", "Taxa de fatalidade (%)"),
format.args = list(big.mark = ".")
) %>%
kable_styling(bootstrap_options = c("striped", "hover")) %>%
row_spec(which(tab_class$classificacao == "ACIDENTE"),
bold = TRUE, color = "white", background = "#d73027")
| Classificação | Registros | Com fatalidade | Total de mortes | Taxa de fatalidade (%) |
|---|---|---|---|---|
| INCIDENTE | 10.500 | 0 | 0 | 0.0 |
| INCIDENTE GRAVE | 1.304 | 0 | 0 | 0.0 |
| ACIDENTE | 3.018 | 707 | 1.704 | 23.4 |
Insight: os incidentes são a maioria absoluta dos registros, mas têm taxa de fatalidade praticamente nula, ou seja, são eventos sem dano grave. Quase toda a mortalidade está na categoria acidente, onde cerca de 23% dos registros envolvem ao menos uma fatalidade. A gravidade, portanto, não está no volume de ocorrências, e sim na classificação: poucos acidentes respondem por todas as mortes da base.
Quando o CENIPA investiga um acidente, ele registra os fatores contribuintes, agrupados em áreas (humano, operacional, material). O gráfico interativo abaixo mostra os fatores mais frequentes.
top_fatores <- dados_limpos %>%
filter(!is.na(fator_nome)) %>%
count(fator_nome, fator_area, sort = TRUE) %>%
slice_head(n = 10) %>%
arrange(n) %>% # do menor para o maior, para a barra maior ficar no topo
mutate(fator_nome = factor(fator_nome, levels = fator_nome))
# Construído direto no plot_ly: o ggplotly funde barras de cor única num retângulo só
plot_ly(
top_fatores,
x = ~n, y = ~fator_nome,
color = ~fator_area, colors = "Set2",
type = "bar", orientation = "h",
hovertext = ~paste0(fator_nome, "<br>", n, " registros"),
hoverinfo = "text"
) %>%
layout(
barmode = "stack",
title = "Top 10 fatores contribuintes",
xaxis = list(title = "Número de registros"),
yaxis = list(title = ""),
legend = list(title = list(text = "Área do fator"))
)
Insight: os fatores que mais aparecem são de natureza humana e operacional (julgamento de pilotagem, aplicação de comandos, planejamento de voo), e não falhas mecânicas. Isso bate com uma ideia já conhecida na segurança de voo: a maior parte dos acidentes está ligada a decisão e desempenho humano, não a defeito de máquina. É um achado útil porque mostra que treinamento e procedimentos têm bastante potencial de prevenção.
A próxima pergunta olha só para os acidentes e em que fase do voo eles acontecem.
fases <- dados_limpos %>%
filter(classificacao == "ACIDENTE", !is.na(aeronave_fase_operacao)) %>%
count(aeronave_fase_operacao, sort = TRUE) %>%
slice_head(n = 8) %>%
mutate(fase = reorder(str_to_title(aeronave_fase_operacao), n))
ggplot(fases, aes(x = n, y = fase)) +
geom_col(fill = "#2c7fb8") +
geom_text(aes(label = n), hjust = -0.15, size = 3.5) +
scale_x_continuous(expand = expansion(mult = c(0, 0.12))) +
labs(
title = "Acidentes por fase do voo (Top 8)",
subtitle = "Decolagem e pouso concentram os momentos mais críticos",
x = "Número de acidentes", y = NULL
) +
theme_minimal(base_size = 12)
Insight: os acidentes se concentram nas fases de decolagem e pouso, quando a aeronave está perto do solo, em baixa velocidade e com a tripulação numa carga de trabalho maior. As fases de cruzeiro, mesmo durando bem mais tempo, aparecem com menos acidentes. É a confirmação da velha máxima da aviação de que decolagem e pouso são as etapas mais delicadas do voo.
Entendido o quê e o porquê, a pergunta seguinte é quando: como o número de ocorrências e de mortes se comportou ao longo dos anos? O primeiro gráfico mostra a quantidade de ocorrências por ano, separada por classificação.
por_ano <- dados_limpos %>%
filter(!is.na(classificacao)) %>%
count(ano, classificacao)
g_ano <- ggplot(por_ano,
aes(x = ano, y = n, color = classificacao,
text = paste0(classificacao, "<br>", ano, ": ", n, " registros"))) +
geom_line(aes(group = classificacao), linewidth = 0.9) +
geom_point(size = 1.6) +
scale_color_manual(values = c("INCIDENTE" = "#2c7fb8",
"INCIDENTE GRAVE" = "#fdae61",
"ACIDENTE" = "#d73027"),
name = "Classificação") +
labs(title = "Ocorrências por ano e classificação",
x = "Ano", y = "Número de ocorrências") +
theme_minimal(base_size = 12)
ggplotly(g_ano, tooltip = "text")
Em seguida, só o total de mortes por ano. Como visto em 4.1, a mortalidade vem inteira dos acidentes.
mortes_ano <- dados_limpos %>%
group_by(ano) %>%
summarise(mortes = sum(fatalidades, na.rm = TRUE), .groups = "drop")
ggplot(mortes_ano, aes(x = ano, y = mortes)) +
geom_col(fill = "#922922") +
geom_text(aes(label = mortes), vjust = -0.4, size = 3) +
scale_x_continuous(breaks = seq(2007, 2026, 2)) +
labs(title = "Total de mortes por ano",
x = "Ano", y = "Mortes") +
theme_minimal(base_size = 12)
Insight: o volume de ocorrências registradas cresce ao longo do período, mas isso não quer dizer que voar ficou mais perigoso. Boa parte do aumento reflete mais registros e mais incidentes leves sendo reportados (cultura de notificação e regulação mais rígida), já que são os incidentes que puxam a curva para cima. As mortes, por outro lado, não mostram tendência clara de crescimento e oscilam de um ano para outro. Vale lembrar que 2026 aparece com números baixos por ser um ano incompleto (a coleta foi feita no meio do ano), então esse último ponto deve ser lido com cuidado.
Por fim, a pergunta onde. Primeiro um ranking das Unidades da Federação com mais ocorrências, depois um mapa interativo com a localização dos acidentes que têm coordenadas registradas.
top_uf <- dados_limpos %>%
filter(!is.na(ocorrencia_uf), ocorrencia_uf != "") %>%
count(ocorrencia_uf, sort = TRUE) %>%
slice_head(n = 12) %>%
arrange(n) %>% # menor -> maior, para a UF com mais casos ficar no topo
mutate(ocorrencia_uf = factor(ocorrencia_uf, levels = ocorrencia_uf))
plot_ly(
top_uf,
x = ~n, y = ~ocorrencia_uf,
type = "bar", orientation = "h",
marker = list(color = "#756bb1"),
hovertext = ~paste0("UF: ", ocorrencia_uf, "<br>", n, " ocorrências"),
hoverinfo = "text"
) %>%
layout(
title = "Top 12 estados (UF) por número de ocorrências",
xaxis = list(title = "Número de ocorrências"),
yaxis = list(title = "")
)
# Mantém só acidentes com coordenadas plausíveis dentro do território brasileiro
acidentes_geo <- dados_limpos %>%
filter(classificacao == "ACIDENTE",
!is.na(latitude), !is.na(longitude),
between(latitude, -34, 6),
between(longitude, -74, -33))
leaflet(acidentes_geo) %>%
addProviderTiles(providers$CartoDB.Positron) %>%
addCircleMarkers(
lng = ~longitude, lat = ~latitude,
radius = 4, stroke = FALSE, fillOpacity = 0.6,
clusterOptions = markerClusterOptions(),
popup = ~paste0("<b>", cidade, " (", ocorrencia_uf, ")</b><br>",
"Ano: ", ano, "<br>",
"Tipo: ", ocorrencia_tipo)
)
Insight: as ocorrências se concentram bastante em São Paulo e na região Sudeste, seguida pelo Sul, acompanhando o volume de tráfego aéreo e a quantidade de aeroportos dessas regiões: onde se voa mais, registra-se mais. Ainda assim, o mapa mostra que os acidentes se espalham pelo país todo, inclusive pelo interior e pela região amazônica, onde a aviação de pequeno porte tem papel importante no transporte. Como nem todo registro tem coordenadas, o mapa exibe só os acidentes geolocalizados, mas mesmo assim o padrão de concentração no Sudeste se mantém.
O projeto partiu de uma pergunta ampla: onde, quando e por que acontecem as ocorrências da aviação civil brasileira, e qual o grau de letalidade de cada tipo. Para responder, foi preciso transformar quatro arquivos públicos e desorganizados do CENIPA num único conjunto de análise e percorrer, da visão geral ao detalhe, as classificações, os fatores, as fases de voo, a evolução temporal, o perfil das aeronaves e a distribuição geográfica.
Os dados vieram do portal dados.gov.br, em quatro CSVs relacionais
com codificação Latin-1, separador ; e valores ausentes
mascarados. O trabalho seguiu o fluxo clássico de ciência de dados:
importação, junção, limpeza e análise exploratória, tudo em R com o
tidyverse. A decisão técnica mais importante foi agregar as
tabelas de um para muitos antes de juntá-las, preservando o tipo e o
fator principais de cada ocorrência sem multiplicar linhas. A partir
daí, as variáveis derivadas (ano, faixa de horário, indicador de
fatalidade, nível de dano ordenado) abriram caminho para as análises,
apresentadas com tabelas e gráficos estáticos e interativos.
Os resultados se reforçam e contam uma história coerente:
Para o CENIPA e a ANAC, os dados sugerem que campanhas e fiscalização rendem mais se focadas em decolagem e pouso, em fatores humanos e na aviação geral. Para empresas aéreas e escolas de aviação, o caminho passa por treinamento de tomada de decisão e procedimentos, não só por manutenção de equipamentos. E para pesquisadores e jornalistas, o conjunto, agora limpo e unificado, vira uma base pronta para acompanhar a evolução da segurança de voo no Brasil.
A análise tem limites que convém deixar claros. Os fatores contribuintes só são investigados em parte das ocorrências (sobretudo acidentes), então não dá para estender essas causas aos incidentes. As contagens brutas refletem o tamanho da frota e a intensidade de notificação, não o risco puro; faltaria um denominador de exposição (como horas de voo ou número de decolagens) para comparações justas. O mapa mostra apenas os registros com coordenadas válidas, e o ano de 2026 está incompleto. Além disso, a agregação guardou só o tipo e o fator principais, deixando os secundários de fora.
Como próximos passos, seria interessante normalizar as ocorrências por movimentos ou horas de voo, construir um mapa coroplético por estado com dados oficiais de fronteiras, modelar a severidade em função das variáveis disponíveis e cruzar a base com dados de frota para medir risco relativo. Mesmo com esses limites, a análise cumpre o objetivo de transformar quatro arquivos brutos numa leitura clara dos padrões de segurança da aviação civil brasileira.