forked from paulofelipe/livro_intro_r
-
Notifications
You must be signed in to change notification settings - Fork 6
/
04-manipulando_dados.Rmd
executable file
·726 lines (516 loc) · 31.4 KB
/
04-manipulando_dados.Rmd
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
# Manipulando os dados
Neste capítulo, usaremos estes pacotes:
```{r 04-manipulando-dados-2}
library(nycflights13)
library(tidyverse)
```
```{r 04-manipulando-dados-1, eval=TRUE, echo=FALSE, message=FALSE}
df <- read_csv2("dados/Ano-2020.csv")
```
Após obter uma boa fonte de dados, e carregá-los para poder trabalhá-los no R, você certamente precisará realizar algumas limpezas e manipulações para que os dados estejam no ponto ideal para as fases finais de uma análise: execução de modelos econométricos, visualizações de dados, tabelas agregadas, relatórios etc. A realidade é que, na prática, os dados nunca estarão do jeito que você de fato precisa. Portanto, é fundamental dominar técnicas de manipulação de dados.
Entendamos a manipulação de dados como o ato de transformar, reestruturar, limpar, agregar e juntar os dados. Para se ter uma noção da importância dessa fase, alguns estudiosos da área de Ciência de Dados costumam afirmar que 80% do trabalho é encontrar uma boa fonte de dados, limpar e preparar os dados, sendo que os 20% restantes seriam o trabalho de aplicar modelos e realizar alguma análise propriamente dita.
>80% of data analysis is spent on the process of cleaning and preparing the data (Dasu and Johnson, 2003).
>Data preparation is not just a first step, but must be repeated many over the course of analysis as new problems come to light or new data is collected (Hadley Wickham).
## Tipos de Variáveis e Colunas
Existem diversos tipos de objetos, e cada tipo "armazena" um conteúdo diferente, desde tabelas de dados recém-carregados a textos, números, ou simplesmente a afirmação de verdadeiro ou falso (Boleano).
```{r 04-manipulando-dados-3}
inteiro <- 928
outro.inteiro <- 5e2
decimal <- 182.93
caracter <- 'exportação'
logico <- TRUE
outro.logico <- FALSE
```
Repare nas atribuições acima. Usaremos a função `class()` para ver o tipo de cada uma:
```{r 04-manipulando-dados-4}
class(inteiro)
class(outro.inteiro)
class(decimal)
class(caracter)
class(logico)
class(outro.logico)
```
Esses são alguns dos tipos básicos de objetos/variáveis no R. Para valores inteiros ou decimais, `numeric` , `character` para valores textuais e `logical` para valores lógicos (verdadeiro ou falso). Existe também o tipo `integer`, que representa apenas números inteiros, sem decimais, porém, na maioria das vezes, o R interpreta o `integer` como `numeric`, pois o `integer` também é um `numeric`.
Além dos tipos básicos, existem também os tipos "complexos", que são `vector`, `array`, `matrix`, `list`, `data.frame` e `factor`.
Data frame é, provavelmente, o tipo de dado complexo mais utilizado em R. É nele que você armazena conjuntos de dados estruturados em linhas e colunas. Um data frame possui colunas nomeadas, sendo que todas as colunas possuem a mesma quantidade de linhas. Imagine o `dataframe` como uma tabela.
```{r 04-manipulando-dados-5, eval=TRUE}
class(df)
```
```{r 04-manipulando-dados-6}
dim(df)
```
Percebeu o termo `tbl` no output acima? Significa `tibble()`, que, conforme o próprio pacote chamado `tibble` descreve, corresponde a uma moderna implementação da estrutura `data.frame`. A classe `tibble` não possui algumas deficiências da classe `data.frame`, por isso a usaremos sempre que possui. É muito simples transformar um `data.frame` em `tibble`.
```{r 04-manipulando-dados-7}
# carregando um dataset pronto do R
data(iris)
# verificando a classe
class(iris)
# transformando para tibble
iris_tbl <- as_tibble(iris)
# verificando a classe do novo objeto
class(iris_tbl)
```
Imprima no seu console os dois objetos e note a diferença:
```{r 04-manipulando-dados-8, eval = FALSE}
print(iris)
print(iris_tbl)
```
Outro tipo que já utilizamos bastante até agora, mas que não foi detalhado, é o `vector`, ou vetor. Vetores são sequências unidimensionais de valores de um mesmo tipo:
```{r 04-manipulando-dados-9}
#faça as seguintes atribuições
vetor.chr <- c('tipo1', 'tipo2', 'tipo3', 'tipo4')
vetor.num <- c(1, 2, 5, 8, 1001)
vetor.num.repetidos <- c(rep(2, 50)) #usando funcão para repetir números
vetor.num.sequencia <- c(seq(from=0, to=100, by=5)) #usando função para criar sequências
vetor.logical <- c(TRUE, TRUE, TRUE, FALSE, FALSE)
##veja o conteúdo das variáveis
vetor.chr
vetor.num
vetor.num.repetidos
vetor.num.sequencia
vetor.logical
```
Para a criação de vetores, usamos a função de combinação de valores `c()` (combine). Esta função vai combinar todos os parâmetros em um único vetor. Lembre-se: vetores são sequências que contêm apenas um tipo de dado.
Conhecendo o `data.frame` e o `vector`, você será capaz de entender como os dois se relacionam. Cada coluna de um data frame é um vetor. Um data frame pode ter colunas de diferentes tipos, mas cada coluna só pode ter registros de um único tipo.
Ficará mais claro a seguir. Veja como se cria um `data.frame`:
```{r 04-manipulando-dados-10}
#cria-se diferentes vetores
nome <- c('João', 'José', 'Maria', 'Joana')
idade <- c(45, 12, 28, 31)
adulto <- c(TRUE, FALSE, TRUE, TRUE)
uf <- c('DF', 'SP', 'RJ', 'MG')
#cada vetor é uma combinação de elementos de um MESMO tipo de dados
#sendo assim, cada vetor pode ser uma coluna de um data.frame
clientes <- data.frame(nome, idade, adulto, uf)
clientes
str(clientes)
```
### Conversões de tipos de variáveis
Quando é feito o carregamento de algum arquivo de dados no R, ele tenta "deduzir" os tipos de dados de cada coluna. Nem sempre essa dedução sai correta e, eventualmente, você precisará converter de um tipo para o outro. O R tem algumas funções para fazer essas conversões.
```{r 04-manipulando-dados-11}
class("2015")
as.numeric("2015")
class(55)
as.character(55)
class(3.14)
as.integer(3.14)
as.numeric(TRUE)
as.numeric(FALSE)
as.logical(1)
as.logical(0)
```
O R também tenta "forçar a barra", às vezes, para te ajudar. Quando você faz uma operação entre dois tipos diferentes, ele tenta fazer algo chamado **coerção de tipos**, ou seja, ele tenta converter os dados para que a operação faça sentido. Caso o R não consiga fazer a coerção, ele vai mostrar uma mensagem de erro.
Experimente os comandos a seguir no console:
```{r 04-manipulando-dados-12, eval=FALSE}
7 + TRUE
2015 > "2016"
"2014" < 2017
# em alguns casos a coerção irá falhar ou dar resultado indesejado
6 > "100"
"6" < 5
1 + "1"
```
Recomendamos fortemente que sempre se realize as conversões explicitamente com as funções apropriadas ao invés de confiar na coerção do R, a não ser que se tenha certeza do resultado.
### Outros tipos de variáveis
Existem outros tipos de variáveis bastante utilizados. Citaremos alguns deles, pois nesse curso utilizaremos muito pouco os demais tipos.
| Tipo | Descrição | Dimensões | Homogêneo |
|---|:---|---|---|---|
| **vector** | Coleção de elementos simples. Todos os elementos precisam ser do mesmo tipo básico de dado | 1 | Sim |
| **array** | Coleção que se parece com o vector, mas é multidimensional | n | Sim |
| **matrix** | Tipo especial de array com duas dimensões | 2 | Sim |
| **list** | Objeto complexo com elementos que podem ser de diferentes tipos | 1 | Não |
| **data.frame** | Tipo especial de lista, onde cada coluna é um vetor de apenas um tipo e todas as colunas têm o mesmo número de registros. É o tipo mais utilizado para se trabalhar com dados | 2 | Não |
| **factor** | Tipo especial de vector, que só contém valores predefinidos (levels) e categóricos (characters). Não é possível adicionar novas categorias sem criação de novos levels | 1 | Não |
### Valores faltantes e o 'NA'
Em casos onde não existe valor em uma coluna de uma linha, o R atribui `NA`. É muito comum lidar com conjuntos de dados que tenham ocorrências de `NA` em alguns campos. É importante saber o que se fazer em casos de `NA`, e nem sempre a solução será a mesma: varia de acordo com as suas necessidades.
Em algumas bases de dados, quem gera o dado atribui valores genéricos como `999` ou até mesmo um "texto vazio", `' '`. Neste caso, você provavelmente terá que substituir esses valores "omissos" por `NA`. Imputar dados em casos de `NA` é uma das várias estratégias para lidar-se com ocorrência de missing no conjunto dos dados.
Seguem algumas funções úteis para lidar-se com `NA`:
- A função `summary()` pode ser usada para averiguar a ocorrência de `NA`.
- A função `is.na()` realiza um teste para saber se a variável/coluna possui um valor `NA`. retorna TRUE se for `NA` e FALSE se não for.
- A função `complete.cases()` retorna TRUE para as linhas em que todas as colunas possuem valores válidos (preenchidos) e FALSE para as linhas em que, em alguma coluna, existe um `NA`. Ou seja, esta função diz quais são as linhas (amostras) completas em todas as suas características (campos).
- Algumas funções possuem o argumento `na.rm`, ou semelhantes, para desconsiderar `NA` no cálculo. É o caso da função `mean()` ou `sum()`.
Por exemplo:
```{r 04-manipulando-dados-13}
data("airquality") # carrega uma base de dados pré-carregada no R
```
```{r 04-manipulando-dados-14}
summary(airquality) # verificando ocorrência de NA
```
```{r 04-manipulando-dados-15}
is.na(airquality$Ozone)
```
## Estruturas de Controle de Fluxo
Para auxiliar no processo de manipulação de dados, você eventualmente precisará de algumas técnicas e estruturas de controle de fluxo. Estruturas para controle de fluxo nada mais são do que loops e condições. São estruturas fundamentais para qualquer linguagem de programação.
### If e Else
A estrutura condicional é algo bastante intuitivo. A estrutura de if (se) e else (então) usa os operadores lógicos apresentados anteriormente. Se a condição do `if()` for verdadeira, executa-se uma tarefa específica, se for falsa, executa-se uma tarefa diferente. A estrutura parece algo do tipo:
```{r 04-manipulando-dados-16, eval=FALSE}
if( variavel >= 500 ) {
#executa uma tarefa se operação resultar TRUE
} else {
#executa outra tarefa se operação resultar FALSE
}
```
Da mesma forma, existe uma função que gera o mesmo resultado, o `ifelse()` (e uma do pacote `dplyr`, o `if_else()`).
```{r 04-manipulando-dados-17, eval=FALSE}
ifelse(variavel >= 500, 'executa essa tarefa se TRUE', 'executa outra se FALSE')
```
Existe uma diferença entre as duas formas de "if else": a estrutura `if() {} else {}` só opera variáveis, uma por uma, já a estrutura `ifelse()` opera vetores, ou seja, consegue fazer a comparação para todos os elementos. Isso faz com que a forma `if() {} else {}` seja mais utilizada para comparações fora dos dados, com variáveis avulsas. Já a estrutura `ifelse()` é mais usada para comparações dentro dos dados, com colunas, vetores e linhas.
Qualquer uma dessas estruturas pode ser "aninhada", ou seja, encadeada. Por exemplo:
```{r 04-manipulando-dados-18}
a <- 9823
if(a >= 10000) {
b <- 'VALOR ALTO'
} else if(a < 10000 & a >= 1000) {
b <- 'VALOR MEDIO'
} else if(a < 1000) {
b <- 'VALOR BAIXO'
}
b
```
Ou ainda:
```{r 04-manipulando-dados-19}
a <- 839
c <- ifelse(a >= 10000, 'VALOR ALTO', ifelse(a < 10000 & a >= 1000, 'VALOR MEDIO', 'VALOR BAIXO'))
c
```
### Loops
Trata-se de um dos conceitos mais importantes de qualquer linguagem de programação, em R não é diferente. Loops (ou laços) repetem uma sequência de comando quantas vezes você desejar, ou até que uma condição aconteça, variando-se alguns aspectos entre uma repetição e outra.
Supondo que você tenha que ler 400 arquivos de dados que você obteve de um cliente. Você vai escrever 400 vezes a funcão de leitura? Nesse caso, basta fazer um loop para percorrer todos os arquivos da pasta e ler um por um com a função de leitura.
#### For
O `for()` é usado para realizar uma série de ordens para uma determinada sequência ou índices (vetor). Sua sintaxe é bem simples:
```{r 04-manipulando-dados-20}
for(i in c(1, 2, 3, 4, 5)) {
print(i^2)
}
```
Para cada valor (chamamos esse valor de `i`) dentro do vetor `c(1, 2, 3, 4, 5)`, execute o comando `print(i^2)`. Qualquer outro comando dentro das chaves `{ ... }` seria executado para cada valor do vetor.
Para entendermos melhor, vamos repensar o exemplo das séries usando o `for()`.
```{r 04-manipulando-dados-21}
lista.de.arquivos <- list.files('dados/dados_loop') #lista todos os arquivos de uma pasta
is.vector(lista.de.arquivos)
for(i in lista.de.arquivos) {
print(paste('Leia o arquivo:', i))
#exemplo: read_delim(i, delim = "|")
}
```
Também é possível utilizar loop com if. No exemplo a seguir, queremos ver todos os números de 1 a 1000 que são divisíveis por 29 e por 3 ao mesmo tempo. Para isso, utilizaremos o operador `%%`, que mostra o resto da divisão. Se o resto for zero, é divisível.
```{r 04-manipulando-dados-22}
for(i in 1:1000){
if((i %% 29 == 0) & (i %% 3 == 0)){
print(i)
}
}
```
#### While
O `while()` também é uma estrutura de controle de fluxo do tipo loop, mas, diferentemente do `for()`, o while executa as tarefas repetidamente até que uma condição seja satisfeita, não percorrendo um vetor.
```{r 04-manipulando-dados-23}
i <- 1
while(i <= 5){
print(i)
i <- i + 1
}
```
O uso do while é um pouco menos intuitivo, mas não menos importante. O while é mais apropriado para eventos de automação ou simulação, onde tarefas serão executadas quando um "gatilho" for acionado. Um simples exemplo para ajudar na intuição de seu uso é:
```{r 04-manipulando-dados-24, eval=FALSE}
automatico <- list.files('dados/automatico/')
length(automatico) == 0
```
Temos uma pasta vazia. O loop abaixo vai monitorar essa pasta. Enquanto essa pasta estiver vazia, ele estará em execução. Quando você colocar um arquivo dentro dessa pasta, vai mudar a condição `length(automatico) == 0` de `TRUE` para `FALSE` e vai mudar a condição `length(automatico) > 0` de `FALSE` para `TRUE`, disparando todas as tarefas programadas. Usamos a função `Sys.sleep(5)` para que o código espere por mais cinco segundos antes de começar o loop novamente.
```{r 04-manipulando-dados-25, eval=FALSE}
while (length(automatico) == 0) {
automatico <- list.files('dados/automatico/')
if(length(automatico) > 0) {
print('O arquivo chegou!')
print('Inicia a leitura dos dados')
print('Faz a manipulação')
print('Envia email informando conclusão dos cálculos')
} else {
print('aguardando arquivo...')
Sys.sleep(5)
}
}
```
Faça o teste: execute o código acima, aguarde alguns segundos e perceba que nada aconteceu. Crie um arquivo qualquer dentro da pasta `dados/automatico/`. Imediatamente o loop será encerrado e as tarefas executadas. Observe o output em tela.
### Funções
Funções "encapsulam" uma sequência de comandos e instruções. É uma estrutura nomeada, que recebe parâmetros para iniciar sua execução e retorna um resultado ao final. Até o momento, você já usou diversas funções. Vejamos então como criar uma função:
```{r 04-manipulando-dados-26, eval=FALSE}
sua_funcao <- function(parametro1, parametro2){
# sequência de tarefas
return(valores_retornados)
}
# chamada da função
sua_funcao
```
Agora tente entender a seguinte função:
```{r 04-manipulando-dados-27}
montanha_russa <- function(palavra) {
retorno <- NULL
for(i in 1:nchar(palavra)) {
if(i %% 2 == 0) {
retorno <- paste0(retorno, tolower(substr(palavra, i, i)))
} else {
retorno <- paste0(retorno, toupper(substr(palavra, i, i)))
}
}
return(retorno)
}
montanha_russa('teste de função: letras maiúsculas e minúsculas')
montanha_russa('CONSEGUIU ENTENDER?')
montanha_russa('É Fácil Usar Funções!')
```
## Manipulações com R base
Dominar a manipulação de data frames e vetores é muito importante. Em geral, toda manipulação pode ser feita com o R base, mas acreditamos que utilizando técnicas do tidyverse a atividade fica bem mais fácil. Portanto, utilizaremos o `dplyr`, um dos principais pacotes do tidyverse. Porém, alguns conceitos do R base são clássicos e precisam ser dominados.
### Trabalhando com colunas de um data.frame
Para selecionar ou trabalhar separadamente com apenas um campo (coluna) do seu data.frame, deve-se utilizar o `$`. Repare nas funções abaixo e no uso do sifrão.
```{r 04-manipulando-dados-28}
head(airquality$Ozone)
tail(airquality$Ozone)
class(airquality$Ozone) # Informa o tipo da coluna
is.vector(airquality$Ozone) # Apenas para verificar que cada coluna de um data.frame é um vector
```
```{r 04-manipulando-dados-29}
unique(df$sgPartido) # Função que retorna apenas os valores únicos, sem repetição, de um vetor
```
Lembre-se sempre: cada coluna de um data.frame é um vetor, portanto todos os registros (linhas) daquela coluna devem ser do mesmo tipo. Um data.frame pode ser considerado um conjunto de vetores nomeados, todos do mesmo tamanho, ou seja, todos com a mesma quantidade de registros.
Usando termos mais técnicos, um data frame é um conjunto de dados HETEROGÊNEOS, pois cada coluna pode ser de um tipo, e BIDIMENSIONAL, por possuir apenas linhas e colunas. Já o vetor é um conjunto de dados HOMOGÊNEO, pois só pode ter valores de um mesmo tipo, e UNIDIMENSIONAL.
Com esses conceitos em mente fica mais fácil entender o que mostraremos a seguir:
```{r 04-manipulando-dados-30}
vetor <- c(seq(from=0, to=100, by=15)) #vetor de 0 a 100, de 15 em 15.
vetor #lista todos os elementos
vetor[1] #mostra apenas o elemento na posição 1
vetor[2] #apenas o elemento na posição 2
vetor[7] #apenas o elemento na posição 7
vetor[8] #não existe nada na posição 8...
```
A notação `[]` é usada para selecionar o elemento em uma ou mais posições do vetor.
```{r 04-manipulando-dados-31}
vetor[c(2,7)] #selecionando mais de um elemento no vetor
```
Uma notação parecida é usada para selecionar elementos no `data.frame`. Porém, como já comentamos, data frames são BIDIMENSIONAIS. Então usaremos a notação `[,]` com uma vírgula separando qual a linha (posição antes da vírgula) e a coluna (posição após a vírgula) que queremos selecionar.
```{r 04-manipulando-dados-32}
df[10, ] #linha 10, todas as colunas
df[72, 3] #linha 72, coluna 3
df[c(100, 200), c(2,3,4)] # selecionando mais de uma linha e coluna em um data.frame
df[c(10:20), ]
```
Repare na notação c(10:20), você pode usar `:` para criar sequências. Experimente `1:1000`
Também é possível selecionar o item desejado utilizando o próprio nome da coluna:
```{r 04-manipulando-dados-33}
df[1:10, c('sgPartido', 'cpf')]
```
Existem diversas outras formas de seleção e manipulação de dados, como, por exemplo, seleção condicional:
```{r 04-manipulando-dados-34}
head(df[df$sgPartido == 'PT', ])
```
Em todas as comparações do R usamos operadores lógicos. São operações matemáticas em que o resultado é `TRUE` ou `FALSE` (tipo `logic`). Para melhor entendimento, selecionamos alguns operadores lógicos e seus significados:
- `==` igual a: compara dois objetos e se forem iguais retorna TRUE, caso contrário, FALSE;
- `!=` diferente: compara dois objetos e se forem diferentes retorna TRUE, caso contrário, FALSE;
- `|` ou (or): compara dois objetos, se um dos dois for TRUE, retorna TRUE, se os dois forem FALSE, retorna FALSE;
- `&` e (and): compara dois objetos, se os dois forem TRUE, retorna TRUE, se um dos dois ou os dois forem FALSE, retorna FALSE;
- `>`, `>=`, `<`, `<=` maior, maior ou igual, menor, menor ou igual: compara grandeza de dois números e retorna TRUE ou FALSE conforme a condição;
É possível fazer muita coisa com o R base, porém, vamos avançar com as manipulações, utilizando o pacote `dplyr`, por ser mais simples e, por isso, de mais rápido aprendizado.
## Pacote dplyr
O forte do pacote `dplyr` é a sintaxe simples e concisa, o que facilita o aprendizado e torna o pacote um dos preferidos para as tarefas do dia a dia. Também conta como ponto forte sua otimização de performance para manipulação de dados. Ao carregar o pacote `tidyverse`, você já carregará automaticamente o pacote `dplyr`, mas você também pode carregá-lo individualmente:
```{r 04-manipulando-dados-35, eval=FALSE}
install.packages("dplyr")
library(dplyr)
?dplyr
```
```{r 04-manipulando-dados-36, echo=FALSE, message=FALSE, warning=FALSE}
library(dplyr)
```
```{04-manipulando-dados-37, type='rmdtip'}
<strong>Referências:</strong>
[Site do pacote `dplyr`](https://dplyr.tidyverse.org)
```
### Verbetes do dplyr e o operador `%>%`
O `dplyr` cobre praticamente todas as tarefas básicas da manipulação de dados: agregar, sumarizar, filtrar, ordenar, criar variáveis, joins, dentre outras.
As funções do `dplyr` reproduzem as principais tarefas da manipulação, de forma bastante intuitiva. Veja só:
- `select()`
- `filter()`
- `arrange()`
- `mutate()`
- `group_by()`
- `summarise()`
Esses são os principais verbetes, mas existem outros disponíveis, como por exemplo `slice()`, `rename()` e `transmute()`.
Além de nomes de funções intuitivos, o `dplyr` também faz uso de um recurso disponível em boa parte dos pacotes do Hadley, o operador `%>%` (originário do pacote `magrittr`). Este operador encadeia as chamadas de funções de forma que você não vai precisar ficar chamando uma função dentro da outra ou ficar fazendo atribuições usando diversas linhas para concluir suas manipulações. Aliás, podemos dizer que esse operador `%>%`, literalmente, cria um fluxo sequencial bastante claro e legível para todas as atividades de manipulação.
Os 6 principais verbetes listados acima possuem funções derivadas com os sufixos `_at`, `_if` e `_all`, que podem ser muito úteis em arquivos com muitas colunas.
### Select
O `select()` é a função mais simples de ser entendida. É usada para selecionar variáveis (colunas, campos, features...) do seu data frame.
```{r 04-manipulando-dados-38}
df %>% select(urlDocumento, txtDescricao, vlrRestituicao)
```
Você pode, também, fazer uma "seleção negativa", ou seja, escolher as colunas que não quer:
```{r 04-manipulando-dados-39}
df %>% select(-txNomeParlamentar)
df %>% select(-c(txNomeParlamentar, cpf))
```
- `select_at()`: Selecionar um conjunto de variáveis, especificadas pelo nome ou pela posição numérica, podendo aplicar uma função ao nome delas:
```{r 04-manipulando-dados-40}
# manter apenas as colunas que começam com S e transformar o nome para maiusculo
#df %>% select_at(vars(starts_with("vlr")))
# é equivalente a:
df %>% select(starts_with("vlr"))
```
- `select_if()`: Selecionar o conjunto de variáveis do dataframe que atende a um teste lógico:
```{r 04-manipulando-dados-41}
# selecionar apenas as colunas numericas do dataframe
df %>% select_if(is.numeric) %>% head()
```
- `select_all()`: seleciona todas as colunas, opcionalmente aplicando uma função ao nome delas.
```{r 04-manipulando-dados-42}
df %>% select_all(tolower)
```
```{04-manipulando-dados-43, type='rmdtip'}
<strong>Referências:</strong>
[Documentação da função `select()`](https://dplyr.tidyverse.org/reference/select.html)
[Documentação das funções derivadas de `select()`](https://dplyr.tidyverse.org/reference/select_all.html)
```
### Mutate
Para criar novos campos ou transformar campos já existentes, podemos usar a `mutate()`. Ela é útil para, por exemplo, converter classes de colunas:
```{r 04-manipulando-dados-47}
# criar coluna com o nome do senador em minusculo
df <- df %>%
mutate(vlrDocumento = as.numeric(vlrDocumento),
vlrLiquido = as.numeric(vlrLiquido),
vlrRestituicao = as.numeric(vlrRestituicao))
```
Caso o argumento da esquerda em `mutate()` seja um nome de coluna que já existe no dataframe, esta será sobrescrita:
```{r 04-manipulando-dados-48}
df %>%
select(txNomeParlamentar, vlrLiquido) %>%
mutate(txNomeParlamentar = tolower(txNomeParlamentar)) %>%
head()
```
Veja como é simples realizar a operação acima, de transformar uma coluna para minúsculo, para todas as colunas de texto do dataframe com o auxílio de `mutate_if()`, na qual o primeiro argumento é um teste lógico e o segundo é a função a ser aplicada para todas as colunas onde o teste lógico seja `TRUE`.
```{r 04-manipulando-dados-49}
df %>%
# o primeiro argumento de mutate_if
mutate_if(is.character, tolower) %>%
head()
```
```{04-manipulando-dados-50, type='rmdtip'}
<strong>Referências:</strong>
[Documentação da função `mutate()`](https://dplyr.tidyverse.org/reference/mutate.html)
[Documentação das funções derivadas de `mutate()`](https://dplyr.tidyverse.org/reference/mutate_all.html)
```
### Filter
Além de escolher apenas alguns campos, você pode escolher apenas algumas linhas, utilizando alguma condição como filtragem. Para isso, basta utilizar a função `filter`.
```{r 04-manipulando-dados-44}
df %>%
select(cpf, txNomeParlamentar, txtDescricao, vlrDocumento) %>%
filter(vlrDocumento >= 100000)
```
```{r 04-manipulando-dados-45}
df %>% filter(numMes == 9) %>% head()
```
```{04-manipulando-dados-46, type='rmdtip'}
<strong>Referências:</strong>
[Documentação da função `filter()`](https://dplyr.tidyverse.org/reference/filter.html)
[Documentação das funções derivadas de `filter()`](https://dplyr.tidyverse.org/reference/filter_all.html)
```
### Group By e Summarise
O `group_by()` e o `summarise()` são operações que trabalham na agregação dos dados, ou seja, um dado mais detalhado passa a ser um dado mais agregado e agrupado, em consequência disso, menos detalhado. O agrupamento de dados geralmente é trabalhado em conjunção com sumarizações, que usam funções matemáticas do tipo soma, média, desvio padrão etc.
Enquanto o `group_by()` "separa" seus dados nos grupos que você selecionar, o `summarise()` faz operações de agregação de linhas limitadas a esse grupo.
Vale observar que operações de agrupamento e sumarização geralmente DIMINUEM a quantidade de linhas dos seus dados, pois está reduzindo o nível de detalhe. Ou seja, de alguma forma, você está "perdendo" detalhe para "ganhar" agregação.
Como exemplo, utilizaremos os dados disponíveis no pacote nycflights13:
```{r 04-manipulando-dados-51, eval=TRUE, message=FALSE, echo=FALSE}
library(nycflights13)
data("flights")
```
```{r 04-manipulando-dados-52, eval=FALSE}
install.packages("nycflights13")
library(nycflights13)
data("flights")
```
```{r 04-manipulando-dados-53}
str(flights)
```
Gostaríamos de obter a média de atraso da chegada para cada mês. Para isso, primeiro agrupamos no nível necessário e depois sumarizamos.
```{r 04-manipulando-dados-54}
atraso_por_mes <- flights %>%
group_by(month) %>%
summarise(arr_delay_media = mean(arr_delay, na.rm=TRUE),
dep_delay_media = mean(dep_delay, na.rm=TRUE))
atraso_por_mes
```
A função `n()` retorna a quantidade de observacões (linhas) por variável especificada em `group_by()`:
```{r 04-manipulando-dados-55}
# Quantidade de voos por hora do dia
flights %>%
group_by(carrier) %>%
summarise(n_voos = n()) %>%
head()
```
A função `n_distinct()` retorna a quantidade de casos únicos por grupo:
```{r 04-manipulando-dados-56}
# quantas companhias aéreas diferentes operam por aeroporto por mês nos EUA?
flights %>%
group_by(origin, month) %>%
summarise(n_empresas = n_distinct(carrier)) %>%
head(6)
```
```{04-manipulando-dados-57, type='rmdtip'}
<strong>Referências:</strong>
[Documentação da função `group_by()`](https://dplyr.tidyverse.org/reference/group_by.html)
[Documentação da função `summarise()`](https://dplyr.tidyverse.org/reference/summarise.html)
```
### Arrange
A função `arrange()` serve para organizar os dados em sua ordenação. Costuma ser uma das últimas operações, normalmente usada para organizar os dados e facilitar visualizações ou criação de relatórios. Utilizando o exemplo anterior, gostaríamos de ordenar os meses pelas menores médias de decolagem (para ordens decrescentes basta usar o sinal de menos `-`)
```{r 04-manipulando-dados-58}
media <- flights %>%
group_by(month) %>%
summarise(arr_delay_media = mean(arr_delay, na.rm=TRUE),
dep_delay_media = mean(dep_delay, na.rm=TRUE)) %>%
arrange(dep_delay_media)
media
```
```{04-manipulando-dados-59, type='rmdtip'}
<strong>Referências:</strong>
[Documentação da função `arrange()`](https://dplyr.tidyverse.org/reference/arrange.html)
```
## Exercícios
### Parte 1
1) Quais foram os deputados com mais despesas na cota parlamentar (considerando a coluna vlrDocumento)?
2) Quais foram as 5 empresas mais contratadas (considerando a coluna textCNPJCPF)?
3) Qual foi o gasto médio dos deputados, por UF, com a cota parlamentar (considerando a coluna vlrDocumento)?
4) Quais categorias de gastos registraram mais despesas nas lideranças (considerando a coluna txtDescricao)?
5) Quantas linhas da coluna com o PDF da nota fiscal estão com NA (considerando a coluna urlDocumento)?
6) Qual foi o mês com menos gastos (considerando a coluna numMes)?
### Parte 2
Baixe o dataset de anúncios do AirBNB no Rio de Janeiro a partir deste link:
http://data.insideairbnb.com/brazil/rj/rio-de-janeiro/2020-05-24/data/listings.csv.gz
1. Leia o arquivo listings com a função read_csv() e salve no objeto `df_anuncios`
2. Inspecione os dados: funções `summary()` e `glimpse()`
3. A partir do output de `glimpse()`, explique as diferentes classes de objetos no R.
4. Observe o problema nas variáveis de preço
5. Retorne a url (scrape_url) do anúncio mais caro do airbnb
6. Retorne o nome do host (host_name) que tem a maior quantidade de anúncios
7. Retorne a quantidade de hosts por ano em que entrou no airbnb
8. Selecione as colunas name e space e filtre as linhas que contem a palavra praia em space. Dica: Vc pode usar a função `str_detect()` dentro de `filter()` ou de `mutate()`
9. Imóveis que mencionam a palavra praia são em média mais caros?
10. Use `mutate()` para modificar o dataframe criando uma coluna booleana chamada `esgotado` informando se o imovel esta indisponivel para os proximos 30 dias (coluna availability_30)
11. Quais os 5 bairros que possuem mais de 100 anúncios com a maior taxa de anúncios esgotados nos próximos 30 dias? Dica: crie duas colunas com summarise, uma usando n() e outra com mean(esgotado) e depois use filter(), arrange() e head()
12. Retorne a quantidade de anúncios e reviews (number_of_reviews) por bairro, calcule uma taxa de quantidade de reviews por quantidade de anuncios. Os bairros que possuem mais anuncios são, proporcionalmente, os que tem mais reviews?
13. Quais são os diferentes tipos de anúncio (quarto, apt, etc.) que existem? (Coluna room_type)
14. A quantidade de quartos tem relação com o preço dos apartamentos inteiros?
15. DESAFIO
Suponha que você planeja uma viagem para o RJ com mais 1 pessoa de 5 diárias nos...
proximos 30 dias. Você e seu grupo têm alguns critérios de escolha:
* Vocês querem ficar em Ipanema, Copacabana ou Leblon.
* Vocês preferem que o host esteja no mesmo bairro.
* Não desejam pagar um depósito de segurança;
* Querem um apartamento inteiro só para vocês que seja "instant bookable"
* A diária já inclua duas pessoas
Filtre os anúncios que atendem aos critérios acima e crie uma coluna chamada preco_total_viagem,
com a formula sendo: taxa de limpeza + preço da diaria x quantidade de diarias.
Compare os resultados com os do site.
Dica: Comece com o código abaixo, selecionando as colunas importantes
```{r, eval = FALSE}
df_anuncios %>%
select(listing_url, neighbourhood, host_neighbourhood,
availability_30, minimum_nights,
security_deposit, instant_bookable,
guests_included, price, room_type, number_of_reviews,
cleaning_fee, review_scores_rating)
```