Parte 1: organização e visualização de dados usando o tidyverse

Objetivos de aprendizagem

Ao final da aula você será capaz de

  • descrever e entender o funcionamento dos principais verbos do dplyr,
  • combinar os diferentes verbos do dplyr para manipular bases de dados,
  • compreender o que é a gramática de gráficos,
  • criar gráficos usando ggplot2.

Antes de iniciar, vamos instalar o pacote tidyverse, que é uma coleção de bibliotecas criadas para o universo de análise de dados.

install.packages("tidyverse")
library(tidyverse)

Veja todos os pacotes disponíveis em www.tidyverse.org. O pacote dplyr faz parte do universo tidyverse.

O operador pipe ( %>% ) da biblioteca magrittr

A função deste operar é passar o objeto do lado esquerdo como primeiro argumento da função do lado direito:

  • x %>% f(y) é equivalente a f(x,y)

  • y %>% f(x,.,z) é equivalente a f(x,y,z)

Atalho no teclado: Ctrl + Shift + M

Na prática, vamos supor que queremos somar todos os elementos do vetor e em seguida tirar a raiz quadrada desta soma:

vetor <- c(20, 40, 60, 80, 200)

sqrt(sum(vetor))
## [1] 20

Usando o pipe:

vetor %>% sum() %>% sqrt()
## [1] 20

Transformação de Dados com dplyr

Os cinco principais verbos do pacote dplyr são:

  • select(): seleciona colunas de um dataframe
  • filter(): filtra linhas que satisfazem uma condição lógica
  • arrange(): ordena as linhas de acordo com uma coluna
  • mutate(): cria novas colunas
  • summarize(): sumariza as informações

Todas as funções com estes verbos os funcionam de maneira similar:

  1. O primeiro argumento é um data frame
  2. Os próximos argumentos descrevem o que fazer com o data frame
  3. O resultado é um novo data frame

Dados

Vamos considerar a base de dados flights do pacote nycflights13, que lista todos os voos que partiram dos aeroportos da cidade de Nova York em 2013.

library(nycflights13)
data(flights)

A primeira função que vamos ver não se encontra da lista dos principais verbos mencionada acima. Veja a documentalção da função slice (comando: ?slice).

flights %>% 
  slice_head(n = 5)
year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time arr_delay carrier flight tailnum origin dest air_time distance hour minute time_hour
2013 1 1 517 515 2 830 819 11 UA 1545 N14228 EWR IAH 227 1400 5 15 2013-01-01 05:00:00
2013 1 1 533 529 4 850 830 20 UA 1714 N24211 LGA IAH 227 1416 5 29 2013-01-01 05:00:00
2013 1 1 542 540 2 923 850 33 AA 1141 N619AA JFK MIA 160 1089 5 40 2013-01-01 05:00:00
2013 1 1 544 545 -1 1004 1022 -18 B6 725 N804JB JFK BQN 183 1576 5 45 2013-01-01 05:00:00
2013 1 1 554 600 -6 812 837 -25 DL 461 N668DN LGA ATL 116 762 6 0 2013-01-01 06:00:00

Selecionando colunas com select()

Vamos selecionar quatro colunas específicas da base de dados: carrier, year, month e day.

flights %>% 
  select(carrier, year, month, day)

Podemos selecionar todas as colunas, com exceção de algumas, como por exemplo a coluna year.

flights %>% 
  select(-year)

everything() é útil para mover as colunas de lugar ao fazer uma seleção.

flights %>% 
  select(carrier, origin, everything())

Também podemos renomear uma coluna dentro do select.

flights %>% 
  select("ano" = year, month, day, ends_with("delay"))

Filtrando linhas com filter()

Vamos obter somente os dados de voos ocorridos em 01/01/2013.

flights %>% 
  filter(month == 1, day == 1)

Abaixo, outro exemplo de filtro: voos partindo dos aeroportos JF Kennedy ou Newark com destino a Los Angeles.

flights %>% 
  filter(origin %in% c("JFK", "EWR"), dest == "LAX")

Arranjando linhas com arrange()

O código a seguir arranja os dados segundo a ordem crescente da coluna dep_delay.

flights %>% 
  arrange(dep_delay)

Agora usando a ordem decrescente.

flights %>% 
  arrange(desc(dep_delay))

Se você fornecer mais de uma coluna, as demais colunas serão usadas sucessivamente para decidir os empates.

flights %>% 
  arrange(desc(month), day)

Combinando filter(), select() e arrange()

Vamos verificar qual a companhia aérea que teve o voo com maior atraso nos vôos entre JFK e LAX.

flights %>%
  filter(origin == "JFK", dest == "LAX") %>%
  select(carrier, dep_delay, year, month, day) %>%
  arrange(desc(dep_delay)) %>% 
  slice_head(n = 1)

A tabela airlines, também do pacote nycflights13, contém o nome completo das companhias e o respectivo código que aparece na tabela flights.

data(airlines)
airlines %>% 
  filter(carrier == "DL")

Criando variáveis com mutate()

Vamos criar uma variável que mostre a velocidade de cada voo.

flights %>%
  select(year:day, flight, distance, air_time) %>%
  mutate(speed = distance / (air_time / 60))

Note que você também pode se referir às variáveis que criou:

flights %>%
  select(year:day, flight,  distance, air_time) %>%
  mutate(hours = air_time / 60,
         speed = distance / hours)

Para manter apenas as variáveis calculadas, use transmute().

flights %>%
    transmute(hours = air_time / 60,
              speed = distance / hours)

Note que é equivalente a %>% select(hours, speed) no final do código anterior.

Colapsando linhas com summarise()

Vamos calcular o atraso médio de decolagem e a quantidade total de voos.

flights %>%
  filter(!is.na(dep_delay)) %>%
  summarise(mean_delay = mean(dep_delay), 
            number_of_flights = n())

Mudando o comportamento de alguns verbos com group_by()

Vamos calcular o atraso médio de decolagem e a quantidade total de voos, mas agora analisando por companhia aérea e ordenar pela companhia que apresentou o maior atraso médio.

flights %>%
  filter(!is.na(dep_delay)) %>%
  group_by(carrier) %>% 
  summarise(mean_delay = mean(dep_delay), number_of_flights = n()) %>% 
  arrange(desc(mean_delay))

O código abaixo calcula, para cada destino, a distância média dos voos, o tempo de atraso médio na decolagem e o número de voos na base.

flights %>%
  filter(!is.na(distance), !is.na(dep_delay)) %>%
  group_by(dest) %>%
  summarise(count = n(), 
            distance = mean(distance), 
            delay = mean(dep_delay))

Visualização de dados com ggplot2

Você deve instalar e carregar o pacote ggplot2.

# install.packages(ggplot2)
library(ggplot2)

O pacote ggplot2 utiliza a gramática de gráficos. Um gráfico é um mapeamento de dados para atributos estéticos (aesthetics: cor, forma, tamanho), de objetos geométricos (pontos, linhas, barras). Também pode conter transformações estatísticas (stats) dos dados e é desenhado num sistema de coordenadas específico. Facetas podem ser utilizadas para gerar o mesmo gráfico para diferentes subconjuntos da base de dados.

Os componentes básicos de um gráfico ggplot são

Gráfico de dispersão

O código a seguir mescla processamento de dados e criação de uma visualização gráfica. O objetivo é criar um gráfico de dispersão entre dep_delay e arr_delay somente para os voos cuja origem é JFK e o destino é LAX.

flights %>%
  filter(origin == "JFK", dest == "LAX",
         !is.na(dep_delay), !is.na(arr_delay)) %>% 
  ggplot(aes(x = dep_delay, y = arr_delay)) +
  geom_abline(slope = 1, intercept = 0, 
              linetype = "dashed", color = "red") +
  geom_point(alpha = 0.1) +
  labs(x = "Departure delay",
       y = "Arrival delay") +
  theme_bw()

Uma variação deste gráfico seria considerar como origem todos os aeroportos da cidade de NYC. Então podemos adicionar uma estética de cor para diferenciar as diferentes origens.

flights %>%
  filter(dest == "LAX",
         !is.na(dep_delay), !is.na(arr_delay)) %>% 
  ggplot(aes(x = dep_delay, y = arr_delay, color = origin)) +
  geom_abline(slope = 1, intercept = 0, 
              linetype = "dashed", color = "red") +
  geom_point(alpha = 0.3) +
  labs(x = "Departure delay",
       y = "Arrival delay") +
  theme_bw()

Veja que a visualização não é fácil. Uma forma de melhorá-la é adicionando facetas no gráfico.

flights %>%
  filter(dest == "LAX",
         !is.na(dep_delay), !is.na(arr_delay)) %>% 
  ggplot(aes(x = dep_delay, y = arr_delay, color = origin)) +
  geom_abline(slope = 1, intercept = 0, 
              linetype = "dashed", color = "red") +
  geom_point(alpha = 0.1) +
  facet_wrap(vars(origin)) +
  labs(x = "Departure delay",
       y = "Arrival delay") +
  theme_bw() +
  theme(legend.position = "none")

Gráfico de barras

O código abaixo faz um gráfico de barras que mostra os destinos que apresentaram os maiores atrasos médios. Para obter o nome dos aeroportos, mesclamos esses dados com a tabela airports.

flights %>%
  filter(!is.na(arr_delay)) %>%
  group_by(dest) %>%
  summarise(delay = mean(arr_delay)) %>% 
  merge(airports, by.x = "dest", by.y="faa") %>% 
  mutate(name = fct_reorder(name, delay)) %>% 
  slice_max(delay, n = 15) %>% 
  ggplot(aes(name, delay))+
  geom_col()+
  coord_flip()+
  labs(x = NULL,
       y = "Delay (minutes)",
       title = "Destinations with greatest mean delay")+
  theme_minimal()

Gráfico de linhas

O trecho de código abaixo obtem os três destinos com mais voos partindo de NYC em 2013, sumariza o número de voos por mês e faz um gráfico de linhas mostrando a série história ao longo do ano para cada um dos destinos.

top_dest <- flights %>% 
  group_by(dest) %>% 
  summarise(n = n()) %>% 
  slice_max(n, n = 3) %>% 
  select(dest) %>% 
  pull()

flights %>%
  filter(dest %in% top_dest) %>% 
  group_by(dest, month) %>%
  summarise(total = n()) %>% 
  inner_join(airports, by = c("dest" = "faa")) %>% 
  ggplot(aes(month, total, color = name)) +
  geom_line()+
  scale_x_continuous(breaks = 1:12) +
  scale_color_manual(values = c("orange", "green", "blue")) +
  labs(x = "Month", 
       y = "Total of flights",
       color = "Destination") +
  theme_bw()

A depender da história que se quer contar com os dados, podemos editar as configurações de visualização do gráfico.

flights %>%
  filter(dest %in% top_dest) %>% 
  group_by(dest, month) %>%
  summarise(total = n()) %>% 
  inner_join(airports, by = c("dest" = "faa")) %>% 
  ggplot(aes(month, total, color = name)) +
  geom_line()+
  scale_x_continuous(breaks = 1:12) +
  scale_color_manual(values = c("orange", "green", "blue")) +
  ylim(0, NA) +
  labs(x = "Month", 
       y = "Total of flights",
       color = "Destination") +
  theme_bw()+
  theme(legend.position = "bottom",
        legend.direction = "vertical")

Boxplots

O código abaixo obtem os dois destinos mais frequentes partindo de NYC, e as companhias aéreas que voaram pelo menos 100 vezes para estes destinos. Ao construir o gráfico, fazemos a junção dos dados em flights com as tabelas airlines e airports para obter o nome completo das companhias aéreas e o nome completo dos aeroportos, respectivamente.

# top 2 destinos mais voados
top_dest <- flights %>% 
  group_by(dest) %>% 
  summarise(n = n()) %>% 
  slice_max(n, n = 2) %>% 
  select(dest) %>% 
  pull()

# obter as cias que voaram pelo menos 100 vezes nesses trechos
cias <- flights %>% 
  filter(dest %in% top_dest) %>% 
  group_by(carrier, dest) %>% 
  summarise(n = n()) %>% 
  filter(n > 100) %>% 
  select(carrier) %>% 
  pull() %>% 
  unique()

# cria o gráfico
flights %>%
  filter(!is.na(air_time), carrier %in% cias,
         dest %in% top_dest) %>%
  inner_join(airlines, by = c("carrier" = "carrier")) %>%
  inner_join(airports %>% 
               select(airport_name = name, faa),
             by = c("dest" = "faa")) %>% 
  ggplot(aes(x = name, y = air_time)) +
  facet_wrap(vars(airport_name), scales = "free_x") + 
  geom_hline(aes(yintercept = mean),
              data = flights %>%
               filter(!is.na(air_time), carrier %in% cias,
                      dest %in% top_dest) %>% 
               group_by(dest) %>% 
               summarise(mean = mean(air_time)) %>% 
               inner_join(airports %>% 
                            select(airport_name = name, faa),
                          by = c("dest" = "faa")),
             linetype = "dashed", color = "red") +
  geom_boxplot(alpha = 0.5) +
  coord_flip() +
  labs(x = NULL, y = "Air time (minutes)") +
  theme_bw()


Código R

O arquivo com o código R completo feito durante a aula pode ser acessado aqui.


Referências

  1. Wickham, H. Tidy data. Journal of statistical software, v. 59, n. 1, p. 1-23, 2014.

  2. Wickham, Hadley. A layered grammar of graphics. Journal of Computational and Graphical Statistics 19.1 (2010): 3-28.

  3. Livro R for Data Science Wickham, H. and Grolemund, G. 2017.