class: center, middle, inverse, title-slide # Tutorial: R básico +
dplyr
### 1º Meetup R-Ladies São Paulo ### Agosto, 2018 --- class: inverse, center, middle # Olá! Alissa Munerato <br> <a href="mailto:alissamunerato@protonmail.com"><i class="fa fa-envelope fa-fw"></i> alissamunerato@protonmail.com</a><br> Bruna Wundervald <br> <a href="mailto:brunadaviesw@gmail.com"><i class="fa fa-envelope fa-fw"></i> brunadaviesw@gmail.com</a><br> <a href="https://brunaw.com/"><i class="fa fa-link fa-fw"></i> brunaw.com</a><br> <a href="http://github.com/brunaw"><i class="fa fa-github fa-fw"></i> @brunaw</a><br> <i class="fa fa-map-marker fa-fw"></i> São Paulo, SP, Brasil</a> <p> </p> --- class: left # 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 --- class: left # O *tidyverse* > Coleção de pacotes para ciência de dados, que compartilham a mesma filosofia, gramática e estruturas de dados. <img src="img/tidy_workflow.png" width="75%" style="display: block; margin: auto;" /> --- class: left # Pacotes ```r library(tidyverse) tidyverse::tidyverse_packages() ``` * `ggplot2`: gráficos bonitos * `dplyr`: manipulação de dados * `tidyr`: leitura de dados * `readr`: *tidy*zar 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) --- class: left # Pacotes ```r library(tidyverse) tidyverse::tidyverse_packages() ``` * `ggplot2`: gráficos bonitos * **`dplyr`: manipulação de dados** * `tidyr`: leitura de dados * `readr`: *tidy*zar 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) --- class: left # Livro <div class="figure" style="text-align: center"> <img src="img/ds.png" alt="Livro: R for Data Science, Hadley Wickham & Garrett Grolemund" width="35%" /> <p class="caption">Livro: R for Data Science, Hadley Wickham & Garrett Grolemund</p> </div> --- # 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. ```r 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 ## ## ## ``` ```r iris %>% subset(Sepal.Length > mean(Sepal.Length)) %>% summary() ``` --- # Pipe! <div class="figure" style="text-align: center"> <img src="img/pipe.png" alt="Isto não é um cachimbo!" width="25%" /> <p class="caption">Isto não é um cachimbo!</p> </div> ## Atalho no teclado: `ctrl+shift+m` --- background-image: url("https://media.giphy.com/media/3o7btPCcdNniyf0ArS/giphy-downsized.gif") background-position: 50% 90% # 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. --- # Exemplos Base de dados dos personagens do starwars: ```r 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... ``` --- # *base* e *dplyr* - Problema: selecionar apenas algumas colunas de uma base de dados - *base*: selecionar por posição ou nome ```r names(starwars) ``` ``` ## [1] "name" "height" "mass" "hair_color" "skin_color" ## [6] "eye_color" "birth_year" "gender" "homeworld" "species" ## [11] "films" "vehicles" "starships" ``` ```r 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` ```r dados <- starwars %>% select(1, 2, 3) dados <- starwars %>% select(name, height, mass) ``` --- # *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* ```r 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 ``` --- # *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* ```r 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 ``` --- # *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* ```r 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 ``` --- # *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* ```r 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 ``` --- # 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` --- # Exemplos ```r 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 ``` --- # 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. ```r plyr::summarise() dplyr::summarise() ``` * Como posso ver o que está em conflito no meu ambiente? ```r conflicts() %>% head(10) ``` ``` ## [1] "%>%" "filter" "lag" "body<-" "intersect" "kronecker" ## [7] "setdiff" "setequal" "union" ``` --- # Exemplo - dados simulados ```r 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.... ``` --- # Usando `ggplot` direto nos dados ```r 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() ``` <img src="meetup_files/figure-html/unnamed-chunk-20-1.png" style="display: block; margin: auto;" /> --- # Usando estes dados Encontrar a média de gasto por cliente: ```r 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 ``` --- class: center, middle ## *joins* - uniões de bases através de chaves. <p> </p> --- <img src="img/joins.png" width="60%" style="display: block; margin: auto;" /> --- # Exemplo ```r 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 ``` ```r 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 ``` --- # A base à esquerda combinada com a da direita ```r 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 ``` --- # O que é comum entre as duas bases ```r 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 ``` --- # União completa das duas bases ```r 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 ``` --- class: center, middle <img src="img/dplyr.png" width="35%" style="display: block; margin: auto;" /> --- class: bottom, center, inverse background-image: url("https://media.giphy.com/media/l3q2u6MXJJEKiTZIY/giphy.gif") background-position: 50% 40%