class: center, middle, inverse, title-slide .title[ # R de dentro pra fora ] .author[ ### Amanda Shinkawa ] --- class: middle # Cenário -- - Na prática, precisamos fazer operações longas e complexas no R; -- - Uso de várias funções pra um único objetivo, geralmente uma dentro da outra; -- - Funções dentro de funções são chamadas "funções aninhadas" ou, em inglês, "nested functions"; -- - Um grande diferencial na programação é otimizar e reduzir a quantidade de linhas de código; -- - A solução é construir e olhar funções de dentro pra fora. --- class: middle # Exemplo -- - Problema: -- - Filtrar apenas os diamantes que possuem preço por quilate acima da média de preço, usando o banco diamonds, que vem no pacote tidyverse; -- - Necessidade: -- - Achar o preço por quilate, média do preço por quilate e filtrar; -- - Solução: -- 1. Dividir preço por quilate; 2. Achar a média; 3. Encontrar quais são os valores que são acima da média; 4. Filtrar apenas esses valores. --- class: middle # Diamonds -- - Banco de dados: ```r head(diamonds) ``` ``` ## # A tibble: 6 x 10 ## carat cut color clarity depth table price x y z ## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> ## 1 0.23 Ideal E SI2 61.5 55 326 3.95 3.98 2.43 ## 2 0.21 Premium E SI1 59.8 61 326 3.89 3.84 2.31 ## 3 0.23 Good E VS1 56.9 65 327 4.05 4.07 2.31 ## 4 0.29 Premium I VS2 62.4 58 334 4.2 4.23 2.63 ## 5 0.31 Good J SI2 63.3 58 335 4.34 4.35 2.75 ## 6 0.24 Very Good J VVS2 62.8 57 336 3.94 3.96 2.48 ``` --- class: middle # Solução ```r diamantes <- diamonds[which((diamonds$price/diamonds$carat)> mean(diamonds$price/diamonds$carat)),] head(diamantes) ``` ``` ## # A tibble: 6 x 10 ## carat cut color clarity depth table price x y z ## <dbl> <ord> <ord> <ord> <dbl> <dbl> <int> <dbl> <dbl> <dbl> ## 1 0.59 Ideal E VVS2 62 55 2761 5.38 5.43 3.35 ## 2 0.61 Very Good D VVS2 59.6 57 2763 5.56 5.58 3.32 ## 3 0.63 Premium E VVS1 60.9 60 2765 5.52 5.55 3.37 ## 4 0.64 Ideal G VVS1 61.9 56 2766 5.53 5.56 3.43 ## 5 0.58 Ideal G VVS1 61.5 55 2772 5.39 5.44 3.33 ## 6 0.58 Ideal F VVS1 61.7 56 2772 5.33 5.37 3.3 ``` -- - Como construir o código aos poucos? --- class: middle # Diamonds -- <ol> <li> Encontrar o preço por quilate; </ol> ```r diamonds$price/diamonds$carat ``` -- <ol start="2"> <li> Encontrar a média; </ol> ```r mean(diamonds$price/diamonds$carat) ``` ``` ## [1] 4008.395 ``` -- <ol start="3"> <li> Descobrir quais são maiores que a média (retorna um vetor com TRUE e FALSE); </ol> ```r (diamonds$price/diamonds$carat)>mean(diamonds$price/diamonds$carat) ``` --- class: middle # Diamonds -- <ol start="4"> <li> Usar a função which pra pegar os números (posições) de cada item que tiver o preço por quilate maior que a média; </ol> ```r which((diamonds$price/diamonds$carat)>mean(diamonds$price/diamonds$carat)) ``` -- <ol start="5"> <li> Encontrar os diamantes que estão nessas posições; </ol> ```r diamonds[which((diamonds$price/diamonds$carat)> mean(diamonds$price/diamonds$carat)),] ``` -- <ol start="6"> <li> Atribuir ao objeto diamantes; </ol> ```r diamantes <- diamonds[which((diamonds$price/diamonds$carat)> mean(diamonds$price/diamonds$carat)),] ``` --- class: middle # Outra abordagem -- - Às vezes, o código é muito complexo e pode ser difícil visualizar o processo; -- - É mais fácil construir as partes do código separadamente; -- - Depois, é só juntar o código todo e apagar as partes; --- class: middle # Diamonds -- <ol> <li> Construir as partes do problema; </ol> ```r ppq <- diamonds$price/diamonds$carat media <- mean(ppq) ind <- which(ppq>media) diamantes <- diamonds[ind,] ``` -- <ol start="2"> <li> Ir substituindo os objetos criados (primeiro ppq); </ol> ```r ppq <- diamonds$price/diamonds$carat media <- mean(diamonds$price/diamonds$carat) ind <- which(diamonds$price/diamonds$carat>media) diamantes <- diamonds[ind,] ``` --- class: middle # Diamonds -- <ol start="3"> <li> Apagar o ppq, pois já substituí ele em todas as aparições; </ol> ```r media <- mean(diamonds$price/diamonds$carat) ind <- which(diamonds$price/diamonds$carat>media) diamantes <- diamonds[ind,] ``` -- <ol start="4"> <li> Ir substituindo os objetos criados (agora media); </ol> ```r media <- mean(diamonds$price/diamonds$carat) ind <- which(diamonds$price/diamonds$carat>mean(diamonds$price/diamonds$carat)) diamantes <- diamonds[ind,] ``` --- class: middle # Diamonds -- <ol start="5"> <li> Apagar a media; </ol> ```r ind <- which(diamonds$price/diamonds$carat>mean(diamonds$price/diamonds$carat)) diamantes <- diamonds[ind,] ``` -- <ol start="6"> <li> Ir substituindo os objetos criados (por fim, ind); </ol> ```r ind <- which(diamonds$price/diamonds$carat>mean(diamonds$price/diamonds$carat)) diamantes <- diamonds[which(diamonds$price/diamonds$carat> mean(diamonds$price/diamonds$carat)),] ``` -- <ol start="7"> <li> Apagar ind; </ol> ```r diamantes <- diamonds[which(diamonds$price/diamonds$carat> mean(diamonds$price/diamonds$carat)),] ``` --- class: middle # Comparando abordagens -- .pull-left[ - Construindo de dentro pra fora 👍 Mais rápido; 👍 Ajuda a desenvolver lógica de programação; 👎 Maior chance de erros, caso não seja testado parte por parte; 👎 Mais complexo. ] -- .pull-right[ - Construindo separadamente e juntando 👍 Reduz chance de erro; 👍 Mais fácil pra quem está começando; 👎 Mais devagar; ] --- class: middle # Agora, um exemplo mais complexo! -- - Vamos utilizar o banco airquality, que já vem no R; -- - Qual é a quantidade de vento do dia de maior ozônio do mês de menor temperatura média? -- - Vamos quebrar o problema em partes: -- 1. Encontrar a média de temperatura por mês; 2. Encontrar o mês de menor média de temperatura; 3. Selecionar apenas esse mês; 4. Achar o dia desse mês de maior ozônio; 5. Selecionar apenas esse dia; 6. Encontrar a quantidade de vento deste dia. --- class: middle # Airquality -- - Banco de dados: ```r head(airquality) ``` ``` ## Ozone Solar.R Wind Temp Month Day ## 1 41 190 7.4 67 5 1 ## 2 36 118 8.0 72 5 2 ## 3 12 149 12.6 74 5 3 ## 4 18 313 11.5 62 5 4 ## 5 NA NA 14.3 56 5 5 ## 6 28 NA 14.9 66 5 6 ``` --- class: middle # Solução ```r airquality[which.max(airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),'Ozone']),'Wind'] ``` ``` ## [1] 5.7 ``` -- - Como construir o código aos poucos? --- class: middle # Airquality -- <ol> <li> Encontrar a média de temperatura de cada mês; </ol> ```r tapply(airquality$Temp,airquality$Month,mean) ``` ``` ## 5 6 7 8 9 ## 65.54839 79.10000 83.90323 83.96774 76.90000 ``` -- <ol start = "2"> <li> Encontrar o mínimo da temperatura; </ol> ```r which.min(tapply(airquality$Temp,airquality$Month,mean)) ``` ``` ## 5 ## 1 ``` -- <ol start = "3"> <li> Encontrar o número do mês que tem temperatura mínima; </ol> ```r names(which.min(tapply(airquality$Temp,airquality$Month,mean))) ``` ``` ## [1] "5" ``` --- class: middle # Airquality -- <ol start = "4"> <li> Encontrar quais linhas são do mês 5; </ol> ```r airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean))) ``` ``` ## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE ## [13] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE ## [25] TRUE TRUE TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE ## [37] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [49] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [61] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [73] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [97] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [109] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [121] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [133] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ## [145] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE ``` --- class: middle # Airquality -- <ol start = "5"> <li> Encontrar o número dessas linhas; </ol> ```r which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))) ``` ``` ## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 ## [26] 26 27 28 29 30 31 ``` -- <ol start = "6"> <li> Selecionar apenas essas linhas; </ol> ```r head(airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),]) ``` ``` ## Ozone Solar.R Wind Temp Month Day ## 1 41 190 7.4 67 5 1 ## 2 36 118 8.0 72 5 2 ## 3 12 149 12.6 74 5 3 ## 4 18 313 11.5 62 5 4 ## 5 NA NA 14.3 56 5 5 ## 6 28 NA 14.9 66 5 6 ``` --- class: middle # Airquality -- <ol start = "7"> <li> Selecionar apenas o ozônio agora, pra ver qual o dia de maior ozônio; </ol> ```r airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),'Ozone'] ``` ``` ## [1] 41 36 12 18 NA 28 23 19 8 NA 7 16 11 14 18 14 34 6 30 ## [20] 11 1 11 4 32 NA NA NA 23 45 115 37 ``` -- <ol start = "8"> <li> Encontrar o máximo de ozônio; </ol> ```r which.max(airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),'Ozone']) ``` ``` ## [1] 30 ``` --- class: middle # Airquality -- <ol start = "9"> <li> Selecionar apenas a linha de máximo ozônio; </ol> ```r airquality[which.max(airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),'Ozone']),] ``` ``` ## Ozone Solar.R Wind Temp Month Day ## 30 115 223 5.7 79 5 30 ``` -- <ol start = "10"> <li> Selecionar apenas o vento; </ol> ```r airquality[which.max(airquality[which(airquality$Month == names(which.min(tapply(airquality$Temp, airquality$Month,mean)))),'Ozone']),'Wind'] ``` ``` ## [1] 5.7 ``` --- class: middle # Obrigada!