+ - 0:00:00
Notes for current slide
Notes for next slide

Tutorial: R básico + dplyr

1º Meetup R-Ladies São Paulo

Agosto, 2018

1 / 30

Olá!

Alissa Munerato
  alissamunerato@protonmail.com

Bruna Wundervald
  brunadaviesw@gmail.com
  brunaw.com
  @brunaw

  São Paulo, SP, Brasil

 

2 / 30

Relembrando

Classes de objetos:

  • character: texto
  • numeric: números racionais
  • integer: inteiros
  • logical: verdadeiro ou falso
  • factor: categóricos
  • ...

Tipos de objetos:

  • vector: unidimensional, apenas uma classe
  • matriz: bidimensional, apenas uma classe
  • data.frame: lista de vetores
  • list: pode contar diferentes classes
3 / 30

O tidyverse

Coleção de pacotes para ciência de dados, que compartilham a mesma filosofia, gramática e estruturas de dados.

4 / 30

Pacotes

library(tidyverse)
tidyverse::tidyverse_packages()
  • ggplot2: gráficos bonitos
  • dplyr: manipulação de dados
  • tidyr: leitura de dados
  • readr: tidyzar os dados
  • purrr: programação funcional
  • tibble: data.frames simples
  • magrittr: semântica
  • stringr: lidar com strings (texto)
  • forcats: lidar com fatores (classes)
  • lubridate: lidar com datas (classes)
5 / 30

Pacotes

library(tidyverse)
tidyverse::tidyverse_packages()
  • ggplot2: gráficos bonitos
  • dplyr: manipulação de dados
  • tidyr: leitura de dados
  • readr: tidyzar os dados
  • purrr: programação funcional
  • tibble: data.frames simples
  • magrittr: semântica
  • stringr: lidar com strings (texto)
  • forcats: lidar com fatores (classes)
  • lubridate: lidar com datas (classes)
6 / 30

Livro

Livro: R for Data Science, Hadley Wickham & Garrett Grolemund

Livro: R for Data Science, Hadley Wickham & Garrett Grolemund

7 / 30

O magrittr e o pipe

  • O pipe, ou %>%, é um operador que aplica aos valores a sua esquerda operações que estão a direita.

  • Podem ser encadeadas tantas operações quanto se queira.

  • Variáveis temporárias não são criadas.

library(magrittr)
iris %>%
summary()
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
## 1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
## Median :5.800 Median :3.000 Median :4.350 Median :1.300
## Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
## 3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
## Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
## Species
## setosa :50
## versicolor:50
## virginica :50
##
##
##
iris %>%
subset(Sepal.Length > mean(Sepal.Length)) %>%
summary()
8 / 30

Pipe!

Isto não é um cachimbo!

Isto não é um cachimbo!

Atalho no teclado: ctrl+shift+m

9 / 30

O dplyr

Gramática de manipulação de dados, construída através de "verbos".

5 funções principais:

  • mutate(): adicionar novas variáveis, que podem ser funções de outras.
  • select(): seleciona ou descarta variáveis.
  • filter(): filtros por critérios.
  • summarise(): resumir os dados.
  • arrange(): ordenar os dados.

Todas estas operações podem ser combinadas!

  • group_by(): performar operações dentro de grupos.
10 / 30

Exemplos

Base de dados dos personagens do starwars:

library(dplyr)
starwars %>%
glimpse()
## Observations: 87
## Variables: 13
## $ name <chr> "Luke Skywalker", "C-3PO", "R2-D2", "Darth Vader", ...
## $ height <int> 172, 167, 96, 202, 150, 178, 165, 97, 183, 182, 188...
## $ mass <dbl> 77.0, 75.0, 32.0, 136.0, 49.0, 120.0, 75.0, 32.0, 8...
## $ hair_color <chr> "blond", NA, NA, "none", "brown", "brown, grey", "b...
## $ skin_color <chr> "fair", "gold", "white, blue", "white", "light", "l...
## $ eye_color <chr> "blue", "yellow", "red", "yellow", "brown", "blue",...
## $ birth_year <dbl> 19.0, 112.0, 33.0, 41.9, 19.0, 52.0, 47.0, NA, 24.0...
## $ gender <chr> "male", NA, NA, "male", "female", "male", "female",...
## $ homeworld <chr> "Tatooine", "Tatooine", "Naboo", "Tatooine", "Alder...
## $ species <chr> "Human", "Droid", "Droid", "Human", "Human", "Human...
## $ films <list> [<"Revenge of the Sith", "Return of the Jedi", "Th...
## $ vehicles <list> [<"Snowspeeder", "Imperial Speeder Bike">, <>, <>,...
## $ starships <list> [<"X-wing", "Imperial shuttle">, <>, <>, "TIE Adva...
11 / 30

base e dplyr

  • Problema: selecionar apenas algumas colunas de uma base de dados

  • base: selecionar por posição ou nome

names(starwars)
## [1] "name" "height" "mass" "hair_color" "skin_color"
## [6] "eye_color" "birth_year" "gender" "homeworld" "species"
## [11] "films" "vehicles" "starships"
dados <- starwars[ , c(1, 2, 3)] # Seleciona as colunas de posição 1, 2 e 3
# ou
dados <- starwars[ , c("name", "height", "mass")] # Seleciona as colunas nomeadas "name", "height" e "mass"
  • dplyr: selecionar com select
dados <- starwars %>%
select(1, 2, 3)
dados <- starwars %>%
select(name, height, mass)
12 / 30

base e dplyr

  • Problema: remover os NA da coluna de gêneros, selecionar apenas os personagens que tem olho de cor preta, calcular o IMC deles e manter apenas as colunas de interesse.

  • base

dados <- starwars[!is.na(starwars$gender),] # Remove NAs
dados <- dados[dados$eye_color == "black", ] # Faz o filtro
dados$imc <- dados$mass/((dados$height/100)^2) # Cria a variável de IMC
dados <- dados[ , c("name", "gender", "imc")] # Seleciona as colunas
dados <- na.omit(dados)
head(dados, 3)
## # A tibble: 3 x 3
## name gender imc
## <chr> <chr> <dbl>
## 1 Greedo male 24.7
## 2 Nien Nunb male 26.6
## 3 Kit Fisto male 22.6
13 / 30

base e dplyr

  • Problema: remover os NA, selecionar apenas os personagens que tem olho de cor amarela, calcular o imc deles e manter apenas as colunas de interesse.

  • dplyr

dados <- starwars %>%
filter(!is.na(gender), eye_color == "black") %>%
mutate(imc = mass/((height/100)^2)) %>%
select(name, gender, imc) %>%
na.omit()
dados %>% slice(1:3)
## # A tibble: 3 x 3
## name gender imc
## <chr> <chr> <dbl>
## 1 Greedo male 24.7
## 2 Nien Nunb male 26.6
## 3 Kit Fisto male 22.6
14 / 30

base e dplyr

Operações por grupo, por exemplo o cálculo do peso médio para cada gênero, apenas de quem tem olho da cor preta.

  • base
dados <- starwars[!is.na(starwars$gender), ]
dados <- dados[dados$eye_color == "black", ]
dados <- dados[!is.na(dados$mass),]
medias <- lapply(split(dados, as.factor(dados$gender)),
function(x) c(Mean = mean(x$mass)))
medias
## $female
## Mean
## 57
##
## $male
## Mean
## 79.5
15 / 30

base e dplyr

Operações por grupo, por exemplo o cálculo do peso médio para cada gênero, apenas de quem tem olho da cor preta.

  • dplyr
medias <- starwars %>%
filter(!is.na(gender), eye_color == "black", !is.na(mass)) %>%
group_by(gender) %>%
summarise(media = mean(mass))
medias
## # A tibble: 2 x 2
## gender media
## <chr> <dbl>
## 1 female 57
## 2 male 79.5
16 / 30

Vantagens até agora

  • Menos texto escrito (não repetimos o nome da base, não usamos c(),...)
  • Operações encadeadas em um mesmo pipe de forma sequencial
  • Código muito mais claro
  • Resultados em data.frame ou tibble
17 / 30

Exemplos

starwars %>%
na.omit() %>%
dplyr::filter(height < 200) %>%
dplyr::mutate(imc = mass/((height/100)^2)) %>%
dplyr::group_by(species) %>%
dplyr::summarise(qtde = n_distinct(name),
media_imc = mean(imc)) %>%
dplyr::select(species, qtde, media_imc) %>%
dplyr::arrange(media_imc)
## # A tibble: 10 x 3
## species qtde media_imc
## <chr> <int> <dbl>
## 1 Gungan 1 17.2
## 2 Twi'lek 1 17.4
## 3 Mirialan 2 18.8
## 4 Cerean 1 20.9
## 5 Kel Dor 1 22.6
## 6 Human 17 24.8
## 7 Mon Calamari 1 25.6
## 8 Ewok 1 25.8
## 9 Zabrak 1 26.1
## 10 Trandoshan 1 31.3
18 / 30

Exemplos

  • E porque usar os ::?
    • Os :: acesssam funções diretamente do pacote.
    • O dplyr, na verdade, é a nova versão do plyr, focada em data.frames.
    • Eles têm funções com o mesmo nome.
plyr::summarise()
dplyr::summarise()
  • Como posso ver o que está em conflito no meu ambiente?
conflicts() %>% head(10)
## [1] "%>%" "filter" "lag" "body<-" "intersect" "kronecker"
## [7] "setdiff" "setequal" "union"
19 / 30

Exemplo - dados simulados

library(ggplot2)
clientes <- read.table("dados.txt")
clientes %>% glimpse()
## Observations: 40
## Variables: 5
## $ id <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,...
## $ classe <fct> A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A,...
## $ sexo <fct> F, M, F, M, F, M, F, M, F, M, F, M, F, M, F, M, F,...
## $ quantidade <int> 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 2, 3, 2, 2, 2, 1,...
## $ valor_gasto <dbl> 8.26, 7.25, 7.26, 8.79, 5.78, 6.76, 5.94, 7.42, 6....
20 / 30

Usando ggplot direto nos dados

clientes %>%
ggplot(aes(valor_gasto)) +
geom_density(fill = "skyblue3", alpha = 0.5) +
geom_vline(xintercept = mean(clientes$valor_gasto),
linetype = 2, size = 1.1) +
theme_bw()

21 / 30

Usando estes dados

Encontrar a média de gasto por cliente:

clientes %>%
group_by(classe, sexo) %>%
summarise(media_gasto = sum(quantidade * valor_gasto)/n_distinct(id))
## # A tibble: 4 x 3
## # Groups: classe [?]
## classe sexo media_gasto
## <fct> <fct> <dbl>
## 1 A F 11.4
## 2 A M 10.1
## 3 B F 2.94
## 4 B M 4.27
22 / 30

joins - uniões de bases através de chaves.

 

23 / 30

24 / 30

Exemplo

df <- starwars %>% # Uma base apenas com nomes e alturas
filter(height < 165) %>%
select(name, height)
df %>% slice(1:3)
## # A tibble: 3 x 2
## name height
## <chr> <int>
## 1 R2-D2 96
## 2 Leia Organa 150
## 3 R5-D4 97
da <- starwars %>% # Uma base apenas com nomes e pesos
filter(mass < 100) %>%
select(name, mass)
da %>% slice(1:3)
## # A tibble: 3 x 2
## name mass
## <chr> <dbl>
## 1 Luke Skywalker 77
## 2 C-3PO 75
## 3 R2-D2 32
25 / 30

A base à esquerda combinada com a da direita

dplyr::left_join(df, da, by = "name")
## # A tibble: 16 x 3
## name height mass
## <chr> <int> <dbl>
## 1 R2-D2 96 32
## 2 Leia Organa 150 49
## 3 R5-D4 97 32
## 4 Yoda 66 17
## 5 Mon Mothma 150 NA
## 6 Wicket Systri Warrick 88 20
## 7 Nien Nunb 160 68
## 8 Watto 137 NA
## 9 Sebulba 112 40
## 10 Shmi Skywalker 163 NA
## 11 Dud Bolt 94 45
## 12 Gasgano 122 NA
## 13 Ben Quadinaros 163 65
## 14 Cordé 157 NA
## 15 Ratts Tyerell 79 15
## 16 R4-P17 96 NA
26 / 30

O que é comum entre as duas bases

dplyr::inner_join(df, da, by = "name")
## # A tibble: 10 x 3
## name height mass
## <chr> <int> <dbl>
## 1 R2-D2 96 32
## 2 Leia Organa 150 49
## 3 R5-D4 97 32
## 4 Yoda 66 17
## 5 Wicket Systri Warrick 88 20
## 6 Nien Nunb 160 68
## 7 Sebulba 112 40
## 8 Dud Bolt 94 45
## 9 Ben Quadinaros 163 65
## 10 Ratts Tyerell 79 15
27 / 30

União completa das duas bases

dplyr::full_join(df, da, by = "name")
## # A tibble: 55 x 3
## name height mass
## <chr> <int> <dbl>
## 1 R2-D2 96 32
## 2 Leia Organa 150 49
## 3 R5-D4 97 32
## 4 Yoda 66 17
## 5 Mon Mothma 150 NA
## 6 Wicket Systri Warrick 88 20
## 7 Nien Nunb 160 68
## 8 Watto 137 NA
## 9 Sebulba 112 40
## 10 Shmi Skywalker 163 NA
## # ... with 45 more rows
28 / 30

29 / 30
30 / 30

Olá!

Alissa Munerato
  alissamunerato@protonmail.com

Bruna Wundervald
  brunadaviesw@gmail.com
  brunaw.com
  @brunaw

  São Paulo, SP, Brasil

 

2 / 30
Paused

Help

Keyboard shortcuts

, , Pg Up, k Go to previous slide
, , Pg Dn, Space, j Go to next slide
Home Go to first slide
End Go to last slide
Number + Return Go to specific slide
b / m / f Toggle blackout / mirrored / fullscreen mode
c Clone slideshow
p Toggle presenter mode
t Restart the presentation timer
?, h Toggle this help
Esc Back to slideshow