Ocorrências Aeronáuticas na Aviação Civil Brasileira - Códigos - Thiago Marques

Instalando e carregando as bibliotecas

Importando os banco de dados

  • Já facilitaremos transformando em fatores as variáveis strings e também limpando/tratando os diferentes tipos de representação de informações faltantes (NA) que foram utilizados no banco.
#Carregando o arquivo em formato CSV
aeronave = read.csv("aeronave.csv",h=T,encoding = "UTF-8",na.strings = c("", "***", "****", "NULL"),stringsAsFactors = T)
#Carregando o arquivo em formato CSV
ocorrencia = read.csv("ocorrencia.csv",h=T,encoding = "UTF-8",na.strings = c("", "***", "****", "NULL"),stringsAsFactors = T)

Unindo as tabelas (Fazendo o Join)

  • Unindo a tabela aeronaves a tabela ocorrências para identificar as ocorrências de cada aeronave, por meio da chave primária “codigo_ocorrencia” que liga ambas unicamente.
uniao_join = merge(x = ocorrencia, y = aeronave, by = "codigo_ocorrencia", all = T)
  • Fazendo a mesma coisa usando o tidyverse
uniao_join_tidyverse = full_join(ocorrencia,aeronave, by="codigo_ocorrencia")
  • Agora com todas as informações em mãos sobre as aeronaves e respectivas ocorrências, podemos partir para a fase do data quality

  • Vamos excluir a tabela uniao_join_tidyverse para evitar redundâncias e otimizar o espaço na memória.

Excluindo a tabela uniao_join_tidyverse

remove(uniao_join_tidyverse)

Data Quality

Verificando as variáveis faltantes de forma visual

- Por meio desse gráfico, adotamos que o corte de menores que 50% de faltantes seriam as melhores variáveis a se trabalhar, então não vale à pena trabalharmos com as seguintes variáveis:

  • Observalções Faltantes:

    • relatorio_publicado (51%) ;
    • dia_publicacao (51%) ;
    • origem_voo (54,3%) ;
    • destino_voo (58,9%) ;
    • aerodromo (60,2%) ;
    • saida_pista (87,5%) ;
    • quantidade_fatalidades (82,6%) ;

Vamos filtrar o banco então sem essas variáveis:

uniao_join_filtrado = uniao_join %>% select(-c("relatorio_publicado",
                         "dia_publicacao",
                         "origem_voo",
                         "destino_voo",
                         "aerodromo",
                         "saida_pista",
                         "quantidade_fatalidades"
                      )
)

Verificando se foi aplicado corretamente o filtro

dim(uniao_join_filtrado)[2]
## [1] 33
  • Agora ficamos com 33 variáveis, em vez de 40 para analisarmos

Transformando variáveis

  • Nessa etapa vamos analisar se é necessário transformar strings em fatores, informações de data que possam ter sido interpretadas como string e assim vai..
class(uniao_join_filtrado$dia_ocorrencia)
## [1] "factor"
  • Conforme vimos a variável dia_ocorrencia está como fator e não como data, logo iremos transformá-la usando o pacote lubridate, melhor pacote do R para se trabalhar com datas.
uniao_join_filtrado$dia_ocorrencia_data = as_date(uniao_join_filtrado$dia_ocorrencia)
  • Verificando se funcionou
class(uniao_join_filtrado$dia_ocorrencia_data)
## [1] "Date"

Fazendo um resumo geral das 33 variáveis que restaram

summary(uniao_join_filtrado)
##  codigo_ocorrencia         classificacao                            tipo    
##  Min.   :25799     ACIDENTE       :1484   FALHA DO MOTOR EM VOO       :377  
##  1st Qu.:38840     INCIDENTE GRAVE: 559   PERDA DE CONTROLE NO SOLO   :325  
##  Median :45564                            PERDA DE CONTROLE EM VOO    :311  
##  Mean   :43962                            COLISÃO EM VOO COM OBSTÁCULO:142  
##  3rd Qu.:50354                            COM TREM DE POUSO           :130  
##  Max.   :65312                            OUTROS TIPOS                : 87  
##                                           (Other)                     :671  
##           localidade         uf              pais         dia_ocorrencia
##  RIO DE JANEIRO:  65   SP     :442   ARGENTINA :   1   2012-09-24:   6  
##  SÃO PAULO     :  50   RS     :170   BRASIL    :2035   2009-08-26:   5  
##  GOIÂNIA       :  42   MT     :154   COLÔMBIA  :   1   2013-02-16:   5  
##  BRASÍLIA      :  31   PR     :154   INGLATERRA:   1   2010-09-15:   4  
##  MANAUS        :  29   MG     :152   PARAGUAI  :   2   2011-02-05:   4  
##  BELO HORIZONTE:  26   (Other):969   PERU      :   1   2011-09-17:   4  
##  (Other)       :1800   NA's   :  2   URUGUAI   :   2   (Other)   :2015  
##      horario     sera_investigada comando_investigador status_investigacao
##  20:30:00:  55   NÃO :   4        SERIPA-4:486         ATIVA     : 768    
##  20:00:00:  53   SIM :1833        SERIPA-5:372         FINALIZADA:1065    
##  17:00:00:  45   NA's: 206        SERIPA-6:350         REABERTA  :   1    
##  13:00:00:  42                    SERIPA-3:267         NA's      : 209    
##  18:00:00:  42                    SERIPA-2:182                            
##  12:00:00:  41                    SERIPA-1:166                            
##  (Other) :1765                    (Other) :220                            
##            numero_relatorio quantidade_recomendacoes aeronaves_envolvidas
##  A DEFINIR         : 436    Min.   : 0.000           Min.   :1.000       
##  ENCERRADA NO RAI  :  55    1st Qu.: 0.000           1st Qu.:1.000       
##  IG-041/CENIPA/2014:   4    Median : 0.000           Median :1.000       
##  A-026/CENIPA/2013 :   3    Mean   : 1.169           Mean   :1.019       
##  A-035/CENIPA/2013 :   3    3rd Qu.: 1.000           3rd Qu.:1.000       
##  (Other)           :1333    Max.   :83.000           Max.   :4.000       
##  NA's              : 209                                                 
##     dia_extracao.x codigo_aeronave   matricula    codigo_operador
##  2016-07-30:2043   Min.   :    4   PPGBC  :   4   Min.   :  13   
##                    1st Qu.: 9061   PPGMA  :   4   1st Qu.:1821   
##                    Median :11267   PPGMR  :   4   Median :3992   
##                    Mean   :12301   PPGOB  :   4   Mean   :3156   
##                    3rd Qu.:13602   PROAF  :   4   3rd Qu.:3992   
##                    Max.   :39147   PPDLF  :   3   Max.   :6270   
##                                    (Other):2020                  
##       equipamento                         fabricante       modelo    
##  AVIÃO      :1603   NEIVA INDUSTRIA AERONAUTICA:388   AB-115  : 111  
##  HELICÓPTERO: 264   CESSNA AIRCRAFT            :354   EMB-202 :  78  
##  ULTRALEVE  : 151   PIPER AIRCRAFT             :157   EMB-201A:  72  
##  PLANADOR   :  11   EMBRAER                    :155   EMB-810C:  61  
##  ANFÍBIO    :   6   AERO BOERO                 :126   EMB-810D:  38  
##  (Other)    :   3   (Other)                    :753   (Other) :1668  
##  NA's       :   5   NA's                       :110   NA's    :  15  
##       tipo_motor   quantidade_motores peso_maximo_decolagem quantidade_assentos
##  JATO      : 117   Min.   :0.000      Min.   :     0        Min.   :  0.000    
##  PISTÃO    :1601   1st Qu.:1.000      1st Qu.:   844        1st Qu.:  2.000    
##  SEM TRAÇÃO:  10   Median :1.000      Median :  1633        Median :  4.000    
##  TURBOEIXO : 148   Mean   :1.244      Mean   :  5330        Mean   :  8.929    
##  TURBOÉLICE: 139   3rd Qu.:2.000      3rd Qu.:  2155        3rd Qu.:  6.000    
##  NA's      :  28   Max.   :4.000      Max.   :285990        Max.   :301.000    
##                    NA's   :9                                NA's   :18         
##  ano_fabricacao        pais_registro  categoria_registro    categoria_aviacao
##  Min.   :   0   BRASIL        :2000   TPP    :760        PARTICULAR  :760    
##  1st Qu.:1975   ESTADOS UNIDOS:  22   PRI    :359        INSTRUÇÃO   :370    
##  Median :1986   PARAGUAI      :   7   TPX    :272        TÁXI AÉREO  :272    
##  Mean   :1902   PORTUGAL      :   2   SAE-AG :196        EXPERIMENTAL:202    
##  3rd Qu.:1999   ÁFRICA DO SUL :   1   PET    :193        AGRÍCOLA    :196    
##  Max.   :2015   ALEMANHA      :   1   (Other):254        (Other)     :218    
##  NA's   :4      (Other)       :  10   NA's   :  9        NA's        : 25    
##             fase_operacao      tipo_operacao       nivel_dano  
##  POUSO             :391   PRIVADA     :775   DESTRUÍDA  : 352  
##  DECOLAGEM         :352   INSTRUÇÃO   :366   LEVE       : 261  
##  CRUZEIRO          :237   TÁXI AÉREO  :273   NENHUM     : 168  
##  CORRIDA APÓS POUSO:189   AGRÍCOLA    :266   SUBSTANCIAL:1193  
##  ESPECIALIZADA     :115   EXPERIMENTAL:153   NA's       :  69  
##  INDETERMINADA     :103   (Other)     :184                     
##  (Other)           :656   NA's        : 26                     
##     dia_extracao.y dia_ocorrencia_data 
##  2016-07-30:2043   Min.   :2006-01-02  
##                    1st Qu.:2009-10-11  
##                    Median :2012-01-22  
##                    Mean   :2011-09-19  
##                    3rd Qu.:2013-12-01  
##                    Max.   :2015-12-31  
## 

Visualização de dados

Quantidade de ocorrências por ano:

#Tabela com as ocorrências por ano
ocorrencias_ano <- as.data.frame(table(year(ocorrencia$dia_ocorrencia)))
## Warning: tz(): Don't know how to compute timezone for object of class factor;
## returning "UTC". This warning will become an error in the next major version of
## lubridate.
ggplot(data = ocorrencias_ano, aes(x = Var1,y = Freq)) +
  geom_bar(aes(fill = Var1),stat = "identity", show.legend = F) +
  xlab("Ano") + 
  ylab("Quantidade de ocorrências") +
  ggtitle("Quantidade de ocorrências de acidentes e incidentes aeronáticos - 2006 a 2015 

Total: 2027 Ocorrências") + 
  geom_text(aes(label = Freq), vjust=-0.2, color="black") +
  scale_fill_brewer(palette="BrBG")

  • A quantidade de acidentes e incidentes graves aparenta ter uma tendência crescente de 2006 a 2012 e decresce a partir de 2013 a 2015, tendo seu pico em 2012, chegando a 287 acidentes, o que correponde a 14,15 % do total de acidentes no período estudado.

Quantidade de aeronaves envolvidas em acidentes por ano:

uniao_join_filtrado %>%
  group_by(ano = as.factor(year(dia_ocorrencia_data))) %>%
  summarise(total = sum(aeronaves_envolvidas)) %>% 
  ggplot(aes(x = ano, y = total)) +
  geom_bar(aes(fill = ano),stat = "identity", show.legend = F) +
  xlab("Ano") + 
  ylab("Quantidade de Aeronaves") +
  ggtitle("Quantidade de aeronaves envolvidas nos acidentes - 2006 a 2015") + 
  geom_text(aes(label = total), vjust=-0.2, color="black") +
  scale_fill_brewer(palette="BrBG")

- Segue o mesmo padrão do número de ocorrências de acidentes, sendo seu pico também em 2012, com 290 casos, correspondendo a 13,94% do total de aeronaves acidentadas no período estudado.

  • OBS: A variável quantidade de vítimas tinhamos muitos dados faltantes (82,6%) e não será possível analisá-la;

Quais são os tipos de classificação de ocorrências mais comuns?

  • Vamos fazer um gráfico de pizza para visualizá-las, uma vez que há poucas categorias.
df_pizza_tab=table(ocorrencia$classificacao)
df_pizza =  data.frame(df_pizza_tab) 
  

colors <- c('rgb(0,204,204)', 'rgb(102,51,0)')

grafico_pizza_iterativo = plot_ly(df_pizza, 
                            labels = ~Var1, 
                            values = ~Freq, 
                            marker = list(colors = colors),
                            type = 'pie') %>%
                            layout(title = 'Classificação dos tipos de ocorrências mais comuns (%) ')

grafico_pizza_iterativo 

Quais são os níveis de dano na aeronave mais comuns?

  • Vamos fazer um gráfico de pizza para visualizá-las, uma vez que há poucas categorias.
df_pizza_tab=table(uniao_join_filtrado$nivel_dano)
df_pizza =  data.frame(df_pizza_tab) 
  

colors <- c('rgb(0,204,204)', 'rgb(102,51,0)')

grafico_pizza_iterativo = plot_ly(df_pizza, 
                            labels = ~Var1, 
                            values = ~Freq, 
                            marker = list(colors = colors),
                            type = 'pie') %>%
                            layout(title = 'Classificação dos tipos de nível de dano mais comuns (%) ')

grafico_pizza_iterativo 

Quais são os equipamentos são mais comuns?

  • Vamos fazer um gráfico de pizza para visualizá-las, uma vez que há poucas categorias.
df_pizza_tab=table(uniao_join_filtrado$equipamento)
df_pizza =  data.frame(df_pizza_tab) %>% top_n(3) 
## Selecting by Freq
colors <- c('rgb(0,204,204)', 'rgb(102,51,0)')

grafico_pizza_iterativo = plot_ly(df_pizza, 
                            labels = ~Var1, 
                            values = ~Freq, 
                            marker = list(colors = colors),
                            type = 'pie') %>%
                            layout(title = 'top 3 Classificação dos tipos de equipamento aéreo (%) ')

grafico_pizza_iterativo 

Quais são os Status de investigação existentes?

df_pizza_tab=table(uniao_join_filtrado$status_investigacao)
df_pizza =  data.frame(df_pizza_tab) 
  

colors <- c('rgb(0,204,204)', 'rgb(102,51,0)')

grafico_pizza_iterativo = plot_ly(df_pizza, 
                            labels = ~Var1, 
                            values = ~Freq, 
                            marker = list(colors = colors),
                            type = 'pie') %>%
                            layout(title = 'Status de investigação (%) ')

grafico_pizza_iterativo 
  • Número de Ocorrências por UF
#tabela da quantidade de ocorrências totais por UF
dados_uf = uniao_join_filtrado %>% select(uf) %>%
  group_by(uf) %>%
  summarise(quantidade = n()) %>%
  arrange(desc(quantidade)) %>%
  head(10)

dados_uf$uf_fator = factor(dados_uf$uf,
                           levels = c("SP",
                                      "RS",
                                      "MT",
                                      "PR",
                                      "MG",
                                      "GO",
                                      "RJ",
                                      "PA",
                                      "BA",
                                      "AM"
                                      #"MT",
                                      #"RO",
                                      #"CE",
                                      #"MS",
                                      #"PB",
                                      #"RN",
                                      #"PI",
                                      #"MA",
                                      #"DF",
                                      #"PA",
                                      #"AL",
                                      #"TO",
                                      #"SE",
                                      #"AC",
                                      #"RR",
                                      #"AM",
                                      #"AP")
                                      )
)
                                      
grafico_barras_uf = ggplot(data=dados_uf, aes(x=uf_fator, y=quantidade, fill=uf_fator)) +
  geom_bar(stat="identity", position=position_dodge(), colour="black") +
  ggtitle("Top 10 Total de ocorrências por UF") + 
  xlab("UF") + ylab("Total de ocorrências") +
  theme(axis.text.x = element_text(angle = -90, vjust = 0.5, hjust=1)) +
  scale_fill_brewer(palette="BrBG")

ggplotly(grafico_barras_uf)

Ocorrências por tipo de problema

tipooco <- ocorrencia%>%
  group_by(tipo)%>%
  count(tipo)

#Ordenação
tipooco$tipo <- factor(tipooco$tipo, 
                                         levels = tipooco$tipo[order(tipooco$n, decreasing = F)])

tipooco%>%
  filter(n > 120)%>%
  ggplot(aes(x = tipo, y = n)) + coord_flip() +
  geom_bar(aes(fill = tipo),stat = "identity", show.legend = F) +
  xlab("Tipos de ocorrência") + ylab("Quantidade de ocorrências") +
  ggtitle("Ocorrências por tipo de problema") + 
  geom_text(aes(label = n), vjust= 0.4, hjust = 0.6, color="black")+
  theme(axis.text.y = element_text(size = 6))+
   scale_fill_brewer(palette="BrBG")

tipooco <- ocorrencia%>%
  group_by(tipo)%>%
  count(tipo)

#Ordenação
tipooco$tipo_fator <- factor(tipooco$tipo, 
                                         levels = tipooco$tipo[order(tipooco$n, decreasing = T)])

#Gráfico de Pareto dos acidentes por tipo de pista
ggplot2::ggplot(tipooco, aes(x = tipo_fator, y = n)) +
  ggQC::stat_pareto(
    point.color = "red",
    point.size = 3,
    line.color = "black",
    bars.fill = c("blue", "orange")
  ) +
  theme(axis.text.x = element_text(
    angle = 90,
    hjust = 1,
    vjust = 0.5
  ))+
  scale_fill_brewer(palette="BrBG")
## Warning in RColorBrewer::brewer.pal(n, pal): n too large, allowed maximum for palette BrBG is 11
## Returning the palette you asked for with that many colors

Gráfico de linhas - Peso máximo decolagem por ano

grafico_linhas  =  
  ggplot(uniao_join_filtrado, aes(x=dia_ocorrencia_data,y=peso_maximo_decolagem)) + 
  geom_line(col="red") + 
  #geom_hline(yintercept = c(6000,10000))+
  xlab("Data") + 
  ylab("Peso máximo na decolagem") + 
  ggtitle("Peso máximo na decolagem por ano") + 
  #geom_text(aes(label = peso_maximo_decolagem), vjust=-0.2, color="black") +
  scale_fill_brewer(palette="BrBG")

grafico_linhas               

Gráfico de linhas - Peso máximo decolagem por ano com limites 2 sigma

# Criando limites inferiores e superiores (3 Sigma)
l1=mean(uniao_join_filtrado$peso_maximo_decolagem)-3*sd(uniao_join_filtrado$peso_maximo_decolagem)

l2=mean(uniao_join_filtrado$peso_maximo_decolagem)+3*sd(uniao_join_filtrado$peso_maximo_decolagem)


ggplot(uniao_join_filtrado, aes(x=dia_ocorrencia_data,y=peso_maximo_decolagem)) + 
geom_line(col="red") + 
geom_hline(yintercept = c(l1,l2))+
xlab("Data") + 
ylab("Peso máximo na decolagem") + 
ggtitle("Série de pesos máximos na decolagem por ano") + 
#geom_text(aes(label = peso_maximo_decolagem), vjust=-0.2, color="black") +
scale_fill_brewer(palette="BrBG")

grafico_linhas               

Criando categorias em classes

minimo=min(uniao_join_filtrado$peso_maximo_decolagem)

q2=quantile(uniao_join_filtrado$peso_maximo_decolagem,0.5)

q3=quantile(uniao_join_filtrado$peso_maximo_decolagem,0.75)

maximo=max(uniao_join_filtrado$peso_maximo_decolagem)

uniao_join_filtrado$peso_classes= 
  cut(uniao_join_filtrado$peso_maximo_decolagem, breaks = c(minimo,q2,q3,maximo),
      labels = c("min -|Q2", "Q2-|Q3", "Q3-|max"),
      include.lowest = F)

Contabilizando as frequências por classe na Pizza

df_pizza_tab=table(uniao_join_filtrado$peso_classes)
df_pizza <<- data.frame(df_pizza_tab)

colors <- c('rgb(0,204,204)', 'rgb(102,51,0)')

grafico_pizza_iterativo = plot_ly(df_pizza, 
                            labels = ~Var1, 
                            values = ~Freq, 
                            marker = list(colors = colors),
                            type = 'pie') %>%
                            layout(title = 'Peso máximo decolagem (%) ')


grafico_pizza_iterativo

Box-plot do peso máximo por quartis

grafico_boxplot = ggplot(uniao_join_filtrado %>% na.omit, aes(x=peso_classes, y=peso_maximo_decolagem,fill=peso_classes)) + 
  geom_boxplot()+
  ggtitle("Gráfico de Box-plot do peso máximo na decolagem por quartis")+
  xlab("Label quartis") +
  ylab("Peso máximo na decolagem")+
  scale_fill_brewer(palette="BrBG")
  
grafico_boxplot

Selecionando as ocorrências que ficaram acima de 3 sigma de peso máximo decolagem

uniao_join_filtrado_acima3sigma_peso_decolagem = uniao_join_filtrado %>% filter (peso_maximo_decolagem >l2)
  • Observamos que filtramos 28 ocorrências a serem analisadas

Fazendo o resumo da base reduzida

s = summary(uniao_join_filtrado_acima3sigma_peso_decolagem)
s[1:7,2:10]
##          classificacao                                        tipo  
##  ACIDENTE       :11    CAUSADO POR FENÔMENO METEOROLÓGICO EM VOO:7  
##  INCIDENTE GRAVE:17    OUTROS TIPOS                             :5  
##                        COM TREM DE POUSO                        :2  
##                        FALHA DE SISTEMA / COMPONENTE            :2  
##                        FALHA DO MOTOR EM VOO                    :2  
##                        PERDA DE CONTROLE NO SOLO                :2  
##                        (Other)                                  :8  
##                 localidade       uf             pais       dia_ocorrencia
##  GUARULHOS           : 6   SP     :11   ARGENTINA : 0   2006-01-08: 1    
##  RIO DE JANEIRO      : 4   RJ     : 4   BRASIL    :26   2006-02-21: 1    
##  BRASÍLIA            : 3   DF     : 3   COLÔMBIA  : 1   2006-03-28: 1    
##  SÃO PAULO           : 2   EX     : 2   INGLATERRA: 0   2006-06-16: 1    
##  ÁGUAS INTERNACIONAIS: 1   AM     : 1   PARAGUAI  : 0   2006-09-29: 1    
##  CAMPINAS            : 1   (Other): 6   PERU      : 1   2006-10-31: 1    
##  (Other)             :11   NA's   : 1   URUGUAI   : 0   (Other)   :22    
##      horario   sera_investigada comando_investigador
##  00:00:00: 2   NÃO : 0          CENIPA  :22         
##  01:05:00: 1   SIM :26          SERIPA-4: 4         
##  01:30:00: 1   NA's: 2          SERIPA-3: 1         
##  02:00:00: 1                    SERIPA-5: 1         
##  02:35:00: 1                    EXTERIOR: 0         
##  02:55:00: 1                    SERIPA-1: 0         
##  (Other) :21                    (Other) : 0