Acidentalidade de ciclomobilidade na cidade de São Paulo

Análise do IDECiclo 2018 da Auditoria Cidadã

Os dados

Os dados de acidentalidade estão divididos em três conjuntos, contendo informações a respeito dos acidentes, das vítimas e dos veículos.

Esta análise será realizada com bases de dados previamente preparadas, em procedimento que agregou os dados referentes aos anos de 2011 à 2017, por conjunto.

library(tidyverse)
library(lubridate)
library(gridExtra)

acidentes <- readRDS("data-raw/acidentes-mortos-feridos-2011-2017.rds")
vitimas <- readRDS("data-raw/vitimas-mortos-feridos-2011-2017.rds")
veiculos <- readRDS("data-raw/veiculos-mortos-feridos-2011-2017.rds")

A base de acidentes contem 151159 observações, que correspondem a ocorrências registradas pela CET entre 2011 e 2017. Há ainda 57 colunas, com variáveis descrevendo atributos de cada um dos acidentes, com variações ao longo dos anos.

glimpse(acidentes)
## Observations: 151,159
## Variables: 57
## $ id_acidente    <chr> "D011100001", "D011100002", "D011100003", "D01110…
## $ cadloga        <chr> "33306", "11818", "33667", "33667", "10376", "167…
## $ cadlogb        <chr> NA, NA, NA, NA, NA, "03189", NA, NA, NA, NA, NA, …
## $ alt_num        <chr> "100", "749", "0", "0", "1", "0", "0", "397", "0"…
## $ referencia     <chr> NA, NA, "NC", "NC", NA, NA, "EN - VD GLORIA", NA,…
## $ data_raw       <chr> "02/01/2011", "03/01/2011", "03/01/2011", "03/01/…
## $ hora           <chr> "16:12", "08:40", "11:14", "14:32", "08:42", "14:…
## $ cod_acid       <chr> "2", "2", "2", "2", "2", "4", "2", "2", "4", "4",…
## $ tipo_acidente  <chr> "SI", "CO", "SI", "CT", "CT", "AT", "CT", "CT", "…
## $ talao          <dbl> 20, 33, 41, 45, 144, 161, 212, 328, 333, 357, 366…
## $ automovel      <dbl> 1, 1, 1, 2, 1, 0, 1, 2, 0, 1, 1, 1, 2, 1, 0, 0, 1…
## $ moto           <dbl> 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ onibus         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0…
## $ caminhao       <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ bicicleta      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ moto_taxi      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ onibus_fretado <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ onibus_urbano  <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0…
## $ microonibus    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ van            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ vuc            <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ caminhonete    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ carreta        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ jipe           <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ carroca        <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ outros         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ sem_informacao <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ feridos        <dbl> 2, 1, 1, 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ mortos         <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…
## $ dp             <chr> "01", "01", "01", "01", "01", "01", "01", "01", "…
## $ det            <chr> "HG", "CT", "CT", "CT", "CT", "CT", "CT", NA, "CT…
## $ distrito       <chr> "02", "49", "02", "02", "80", "80", "02", NA, "80…
## $ mapinfo_id     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ fonte          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ viatura        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ veiculos       <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ vitimas        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ dec            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ folha          <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ princ_a        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ princ_b        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ tipo_plac1     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ tipo_plac2     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ tipo_plac3     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ logradouro_a   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ logradouro_b   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ dia__semana    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ dia_semana     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ mes_acidente   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ periodo_dia    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ distrito_atz   <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ pref_reg       <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ tipos_acid     <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ lat            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ long           <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, N…
## $ dataok         <chr> "2011-01-02", "2011-01-03", "2011-01-03", "2011-0…
## $ ano            <dbl> 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2011, 2…

A base de vitimas contem, por sua vez, 185260 observações, cada uma com dados de vítimas dos acidentes registrados pela CET organizados em 17 variáveis.

glimpse(vitimas)
## Observations: 185,260
## Variables: 17
## $ id_acidente   <chr> "D011100001", "D011100001", "D011100002", "D011100…
## $ id_vitima     <chr> "001", "002", "001", "001", "001", "001", "002", "…
## $ id_veiculo    <chr> "01", "01", "01", "01", "01", "01", "01", "01", "0…
## $ sexo          <chr> "M", "M", "M", "M", "M", "M", "F", "M", "M", "F", …
## $ idade         <dbl> 21, 22, 27, 30, 35, 28, 27, 58, 24, 23, NA, 23, 32…
## $ tipo_vitima   <chr> "CD", "PS", "CD", "CD", "CD", "CD", "PS", "PD", "C…
## $ classificacao <chr> "F", "F", "F", "F", "F", "F", "F", "F", "F", "F", …
## $ tipo_veiculo  <chr> "AU", "AU", "MO", "MO", "AU", "MO", "MO", "MO", "A…
## $ estado_alc    <chr> "BR", "BR", "BR", "BR", "BR", "BR", "BR", "BR", "B…
## $ escolaridade  <chr> "7", "5", "7", "5", "5", "7", "5", "8", "8", "8", …
## $ data_raw      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mapinfo_id    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ data_obito    <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ mes_acid      <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ tipo_usuario  <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ dataok        <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…
## $ ano           <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…

Já no conjunto de dados sobre os veículos existem 254989 observações, com os veículos envolvidos nos acidentes constantes na base de acidentes. Há 10 variáveis com atributos dos meios de transporte acidentados.

glimpse(veiculos)
## Observations: 254,989
## Variables: 10
## $ id_acidente           <chr> "D011100001", "D011100002", "D011100002", …
## $ id_veiculo            <chr> "01", "01", "02", "01", "02", "01", "02", …
## $ tipo_veiculo          <chr> "AU", "MO", "AU", "MO", "AU", "AU", "AU", …
## $ sexo_condutor         <chr> "M", "M", "M", "M", "X", "M", "M", "M", "M…
## $ idade_condutor        <dbl> 21, 27, 61, 30, NA, 35, 48, 28, 71, 21, 24…
## $ categoria_habilitacao <chr> "SI", "SI", "SI", "SI", "SI", "SI", "SI", …
## $ usa_cinto_seguranca   <chr> "X", "X", "X", "X", "X", "X", "X", "X", "X…
## $ estado_alc            <chr> "BR", "BR", "BR", "BR", "BR", "BR", "BR", …
## $ escolaridade          <chr> "7", "7", "6", "5", "8", "5", "5", "7", "8…
## $ mapinfo_id            <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA…

Valores ausentes

Como há variáveis que existem em alguns anos, mas não em outros, algumas variáveis não descrevem aspectos dos acidentes, das vítimas e dos veículos para todos os anos. O gráficos abaixo mostram a análise de valores ausentes (NA) nos três conjuntos de dados e explicitam este problema.

theme_set(theme_minimal())

acidentes %>% 
  gather(key, value, -ano) %>% 
  group_by(ano, key) %>% 
  count(na = is.na(value)) %>% 
  mutate(na = if_else(na == TRUE, "Sim", "Não")) %>% 
  ggplot(aes(x = key, y = n, fill = na)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("lightcoral", "lightgrey"), "Valor é NA?") +
  facet_wrap(~ano, ncol = 7, scales = "free_x") +
  labs(title = "Valores ausentes na base de acidentes",
       x = NULL, y = NULL) +
  theme(axis.text.x = element_blank(),
        legend.position = "top") +
  coord_flip()

vitimas %>% 
  gather(key, value, -ano) %>% 
  group_by(ano, key) %>% 
  count(na = is.na(value)) %>% 
  mutate(na = if_else(na == TRUE, "Sim", "Não")) %>% 
  ggplot(aes(x = key, y = n, fill = na)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("lightcoral", "lightgrey"), "Valor é NA?") +
  facet_wrap(~ano, ncol = 7, scales = "free_x") +
  labs(title = "Valores ausentes na base de vítimas",
       x = NULL, y = NULL) +
  theme(axis.text.x = element_blank(),
        legend.position = "top") +
  coord_flip()

veiculos %>% 
  gather(key, value) %>% 
  group_by(key) %>% 
  count(na = is.na(value)) %>% 
  mutate(na = if_else(na == TRUE, "Sim", "Não")) %>% 
  ggplot(aes(x = key, y = n, fill = na)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(values = c("lightcoral", "lightgrey"), "Valor é NA?") +
  labs(title = "Valores ausentes na base de veículos",
       x = NULL, y = NULL) +
  theme(axis.text.x = element_blank(),
        legend.position = "top") +
  coord_flip()

Análise dos acidentes

O número de acidentes vem caindo com os anos

Em 7 anos (2011 a 2017) a CET registrou 151159 acidentes na cidade de São Paulo.

total_acidentes <- acidentes %>%
  group_by(ano = as.factor(ano)) %>% 
  summarise(geral = n(),
            bicicleta = sum(bicicleta, na.rm = TRUE)) %>% 
  mutate(Percentual = round(bicicleta / geral, 3))

p1 <- ggplot(total_acidentes, aes(x = ano, y = geral)) +
  geom_line(group = 1) +
  geom_point(size = 3) +
  geom_hline(aes(yintercept = mean(total_acidentes$geral)),
             linetype = 5, color = "darkgrey", lwd = 1.5) +
  scale_y_continuous(limits = c(0, 30000), breaks = seq(0, 30000, 5000)) +
  labs(title = "Evolução temporal do total anual de acidentes",
       subtitle = "todos os acidentes",
       x = NULL, y = NULL) +
  annotate("text", x = 2, y = 17000, color = "darkgrey",
           label = paste("Média de", round(mean(total_acidentes$geral)),
                         "\nacidentes por ano"),
           fontface = "bold")

p2 <- ggplot(total_acidentes, aes(x = as.factor(ano), y = bicicleta, group = 1)) +
  geom_line(color = "lightcoral") +
  geom_point(size = 3, color = "lightcoral") +
  geom_hline(aes(yintercept = mean(total_acidentes$bicicleta)),
             linetype = 5, color = "darkgrey", lwd = 1.5) +
  scale_y_continuous(limits = c(0, 1000), breaks = seq(0, 1000, 100)) +
  labs(title = NULL, subtitle = "somente bicicleta",
       x = NULL, y = NULL) +
  annotate("text", x = 2, y = 460, color = "darkgrey",
           label = paste("Média de", round(mean(total_acidentes$bicicleta)),
                         "\nacidentes por ano"),
           fontface = "bold")

grid.arrange(p1, p2, ncol = 1)

E o número de mortos também reduziu…

mortalidade <- acidentes %>% 
  group_by(ano = as.factor(ano)) %>% 
  summarise(geral = sum(mortos, na.rm = TRUE)) %>% 
  left_join(
    acidentes %>% 
      filter(bicicleta == 1) %>% 
      group_by(ano = as.factor(ano)) %>% 
      summarise(bicicleta = sum(mortos, na.rm = TRUE)),
    by = "ano"
    ) %>% 
  mutate(taxag = geral / total_acidentes$geral * 100,
         taxab = bicicleta / total_acidentes$bicicleta * 100)

# mortos no geral
p1 <- ggplot(mortalidade, aes(x = ano, y = geral)) +
  geom_point(color = "black", size = 3) +
  geom_line(color = "black", group = 1) +
  geom_hline(aes(yintercept = mean(mortalidade$geral)),
             linetype = 5, color = "darkgrey", lwd = 1.5) +
  scale_y_continuous(breaks = seq(0, 1400, 200)) +
  labs(title = "Número de mortos em acidentes por ano",
       subtitle = "todos os acidentes",
       x = NULL, y = NULL) +
  annotate("text", x = 2, y = 700, color = "darkgrey", fontface = "bold",
           label = paste("Em média", round(mean(mortalidade$geral)),
                         "\nvítimas fatais por ano"))

# mortes com bicicleta
p2 <- ggplot(mortalidade, aes(x = ano, y = bicicleta)) +
  geom_point(color = "lightcoral", size = 3) +
  geom_line(color = "lightcoral", group = 1) +
  geom_hline(aes(yintercept = mean(mortalidade$bicicleta, na.rm = TRUE)),
             linetype = 5, color = "darkgrey", lwd = 1.5) +
  scale_y_continuous(limits = c(0, 55), breaks = seq(0, 55, 10)) +
  labs(title = NULL, subtitle = "somente bicicleta",
       x = NULL, y = NULL) +
  annotate("text", x = 2, y = 35, color = "darkgrey", fontface = "bold",
           label = paste("Em média", round(mean(mortalidade$bicicleta, na.rm = TRUE)),
                         "\nvítimas fatais por ano"))

grid.arrange(p1, p2, ncol = 1)

… mas a taxa de mortalidade cresceu

Aproximadamente 9 pessoas morrem a cada 100 acidentes com bicicleta

mortalidade %>% 
  select(taxag, taxab, ano) %>% 
  gather(key, value, -ano) %>% 
  mutate(key = if_else(key == "taxag", "geral", "bicicleta")) %>% 
  ggplot(aes(x = ano, y = value, colour = key)) +
  geom_point(size = 3) +
  geom_line(aes(group = key)) +
  scale_colour_manual(values = c("lightcoral", "black")) +
  scale_y_continuous(breaks = seq(0, 9, 1)) +
  labs(title = "Evolução anual da taxa de fatalidade",
       subtitle = "n mortos para cada 100 acidentes",
       x = NULL, y = NULL)

Bicicleta é sempre a quinta no ranking de veículos

veiculos_acidentes <- acidentes %>% 
  select(ano, automovel:outros) %>% 
  gather(veiculo, valor, -ano) %>% 
  group_by(ano, veiculo) %>% 
  summarise(total = sum(valor, na.rm = TRUE)) %>% 
  mutate(veiculo = if_else(str_detect(veiculo, "camin"), "caminhoes", veiculo),
         veiculo = gsub("vuc", "caminhoes", veiculo),
         veiculo = gsub("carreta", "outros", veiculo),
         veiculo = if_else(str_detect(veiculo, "onibus"), "onibus", veiculo),
         veiculo = if_else(str_detect(veiculo, "moto"), "moto", veiculo),
         veiculo = gsub("jipe", "automovel", veiculo),
         veiculo = gsub("carroca", "outros", veiculo),
         veiculo = gsub("carroca", "outros", veiculo)) %>% 
  group_by(ano, veiculo) %>% 
  summarise(total = sum(total, na.rm = TRUE)) %>% 
  mutate(bike = if_else(veiculo == "bicicleta", "bicicleta", "outros"))

plot_ano <- function(data){
  veiculos_acidentes %>% filter(ano == data) %>%  
    ggplot(aes(x = reorder(veiculo, -total), y = total, fill = bike)) +
    geom_bar(stat = "identity") +
    scale_fill_manual(values = c("lightcoral", "darkgrey"), guide = FALSE) +
    scale_y_continuous(limits = c(0, 20000)) +
    labs(subtitle = data, x = NULL, y = NULL) +
    theme(axis.text.x = element_text(angle = 90))
}

p <- lapply(c(2011:2014, 2016:2017), function(x) plot_ano(x))

do.call(gridExtra::grid.arrange, c(p, ncol = 6))

Na base de 2015 não há variáveis indicando o envolvimento de tipos de veículos nos acidentes, por isto o gráfico deste ano não mostra nenhum dado..

knitr::kable(
  total_acidentes %>% 
  mutate(Percentual = scales::percent(round(bicicleta / geral, 3))) %>% 
  select(ano, Percentual) %>% 
  spread(ano, Percentual),
  caption = "Peso percentual dos acidentes com bicicleta em relação ao total"
)
Table 1: Peso percentual dos acidentes com bicicleta em relação ao total
2011 2012 2013 2014 2015 2016 2017
3.20% 3.50% 2.80% 2.80% 0.00% 3.50% 3.40%

Colisões e atropelamentos são os acidentes mais comuns

acidentes %>% 
  count(ano = as.factor(ano), tipo_acidente) %>%
  mutate(tipo_acidente = if_else(n < 1000, "Outros", tipo_acidente)) %>%
  group_by(ano, tipo_acidente) %>% 
  summarise(n = sum(n)) %>% 
  group_by(ano) %>% 
  mutate(prop = prop.table(n)) %>% 
  ggplot(aes(x = ano, y = prop, colour = reorder(tipo_acidente, -prop))) +
  geom_point() +
  geom_line(aes(group = tipo_acidente)) +
  scale_colour_brewer(palette = "Set2", "Tipo de\nacidente") +
  scale_y_continuous(labels = scales::percent)