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:

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:

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)

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 %>%
    select(year:day, ends_with("delay"), distance, air_time) %>%
    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))

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.

library(ggplot2)

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)")+
  theme_minimal()


Formato de dados tidy

Dados organizados em formato tidy são facilmente usados para análise e modelagem.

Regras que definem um conjunto de dados tidy [{1}]:

O formato de uma tabela tidy depende do que são considerados variável e observação em um dado contexto.

Como exemplo, veja os dados de casos de tuberculose em diferentes paises, armazenados no pacote tidyr.

library(tidyr)
table1
country year cases population
Afghanistan 1999 745 19987071
Afghanistan 2000 2666 20595360
Brazil 1999 37737 172006362
Brazil 2000 80488 174504898
China 1999 212258 1272915272
China 2000 213766 1280428583

Veja como é simples calcular a taxa de casos por população.

table1 %>% 
  mutate(rate = cases / population * 10000)

Transformando dados em formato tidy

table4a
country 1999 2000
Afghanistan 745 2666
Brazil 37737 80488
China 212258 213766

O que devemos fazer para deixar essa tabela no formato tidy?

Podemos usar a função pivot_longer.

table4a %>% 
  pivot_longer(cols = -country,  
               names_to = "year", 
               values_to = "cases")

Agora, veja este próximo caso.

table2
country year type count
Afghanistan 1999 cases 745
Afghanistan 1999 population 19987071
Afghanistan 2000 cases 2666
Afghanistan 2000 population 20595360
Brazil 1999 cases 37737
Brazil 1999 population 172006362
Brazil 2000 cases 80488
Brazil 2000 population 174504898
China 1999 cases 212258
China 1999 population 1272915272
China 2000 cases 213766
China 2000 population 1280428583

O que devemos fazer para deixar essa tabela no formato tidy?

Podemos usar a função pivot_wider.

table2 %>%
    pivot_wider(names_from = type, 
                values_from = count)

Notas

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

[2]. Todas figuras foram retiradas do livro R for Data Science Wickham, H. and Grolemund, G. 2017.