-
Notifications
You must be signed in to change notification settings - Fork 0
/
10-manipulacao-dados.Rmd
1710 lines (1158 loc) · 58.2 KB
/
10-manipulacao-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
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
output:
html_document: default
pdf_document: default
---
# (PART) Ferramentas modernas do R {-}
# Processamento de dados {#data-wrangle}
<!--
https://moderndive.com/preface.html
Package for handling multiple imputations in a tidy format
https://github.com/njtierney/mputr
https://blog.rstudio.com/2020/05/05/wrangling-unruly-data/?utm_content=buffer24dbf&utm_medium=social&utm_source=linkedin&utm_campaign=buffer
https://rstudio.com/resources/webinars/reproducibility-in-production/
https://education.rstudio.com/blog/2020/07/teaching-the-tidyverse-in-2020-part-1-getting-started/?utm_content=buffer885dc&utm_medium=social&utm_source=linkedin&utm_campaign=buffer
https://joss.theoj.org/papers/10.21105/joss.01686
https://towardsdatascience.com/five-tidyverse-tricks-you-may-not-know-about-c5026d5a19da
-->
```{r setup, include = FALSE}
rm(list = ls())
pcks <- c("knitr", "pander")
easypackages::libraries(pcks)
opts_chunk$set(
prompt = FALSE,
cache = FALSE,
fig.path = "images/",
comment = "#>",
collapse = TRUE,
eval = FALSE # to try pass in travis!
)
source("R/utils.R")
figselect <- '<img src=images/dplyr-select.png" width="20">'
```
Neste capítulo veremos:
- um *quadro de dados* aperfeiçoado, denominado *tibble*
- como arrumar seus dados em uma estrutura conveniente para a análise e visualização de dados
- como reestruturar os dados de uma forma versátil e fácil de entender
- como manipular os dados com uma ferramenta intuitiva e padronizada
Existem diversas ferramentas da base do `r rblue` para realizar as operações listadas acima. Entretanto, elas não foram construídas para um objetivo comum e foram feitas por diferentes desenvolvedores e em diferentes fases da evolução do `r rblue`. Por isso, elas podem parecer confusas, não seguem uma codificação consistente e não foram construídas pensando em uma interface integrada para o processamento de dados. Conseqüentemente, para usá-las é necessários um esforço significativo para entender a estrutura de dados de entrada de cada uma. A seguir, precisamos padronizar suas saídas para que sirvam de entrada para outra função (às vezes de outro pacote) que facilita a realização de uma próxima etapa do fluxo de trabalho.
Muitas coisas no `r rblue` que foram desenvolvidas há 20 anos atrás são úteis até hoje. Mas as mesmas ferramentas podem não ser a melhor solução para os problemas contemporâneos. Alterar os códigos da base do `r rblue` é uma tarefa complicada devido a cadeia de dependências do código fonte e dos pacotes dos milhares de contribuidores. Então, grande parte das inovações no `r rblue` estão ocorrendo na forma de pacotes. Um exemplo é o conjunto de pacotes [*tidyverse*](https://www.tidyverse.org/) desenvolvido para suprir a necessidade de ferramentas efetivas e integradas para ciência de dados (Figura \@ref(fig:tidy-workflow)).
<!---
#A nossa capacidade tecnológica de coletar e armazenar uma quantidade massiva de dados digitalmente demanda ferramentas pragmáticas e acessíveis.
--->
```{r tidy-workflow, out.width="100%", fig.cap="Modelo de ferramentas empregadas em ciência de dados. Adaptado de @Wickham2017.", echo = FALSE, eval = TRUE}
knitr::include_graphics("images/workflowtidy.png")
```
O termo *tidyverse* pode ser traduzido como 'universo arrumado' e consiste em uma coleção de pacotes (Figura \@ref(fig:tidyverse-components)) que compartilham uma interface comum com padrões de estrutura e manipulação de dados [@Wickham-dplyr, @Wickham2014].
O *tidyverse* tem sido amplamente utilizado pela comunidade de usuários e desenvolvedores do `r rblue`. Além de uma abordagem mais coesa e consistente para realizar as tarefas envolvidas no processamento de dados, os códigos são mais eficientes, legíveis e com sintaxe mais fácil de lembrar. Consequentemente, focamos mais nos conceitos e menos na sintaxe.
```{r tidyverse-components, out.width="80%", fig.cap="Coleção de pacotes do *tidyverse*.", echo = FALSE, eval = TRUE}
knitr::include_graphics("images/tidyverse_components.png")
```
O tidyverse enfatiza legibilidade ao invés de desempenho. Para quem está começando a programar ele atenderá à maioria dos processos analíticos, mas pode não ser rápido o suficiente para um sistema de processamento de dados operacional de alta demanda. Se você precisa avançar nesta linha, você precisará se aprofundar em ferramentas específicas (veja por exemplo @Gillespie2017).
## Pré-requisitos
O pacote **tidyverse** torna fácil de instalar e carregar os pacotes do *tidyverse* com apenas uma chamada à função:
```{r, eval = FALSE}
install.packages("tidyverse")
```
E da mesma forma carregamos o conjunto de pacotes com:
```{r, eval = TRUE}
library(tidyverse)
```
```{block, tidyverse-load, type='rmdnote'}
Ao carregar o pacote **tidyverse** é mostrado no console os pacotes que foram carregados. À direita são mostradas as configurações e informações sobre o seu sistema operacional. Na parte inferior, há uma mensagem sobre os conflitos entre as funções da base do R (ou de outros pacotes) que tem mesmo nome que as de algum pacote do *tidyverse*. A função do pacote carregado mais recentemente terá prioridade de uso. No caso acima, a função `filter()` do **dplyr** sobrepôs a função `filter()` do pacote **stats** da base do R. Em situações como esta é melhor deixar explícito no seu código a chamada à função usando `pacote::funcao()`.
```
Neste capítulo além do **tidyverse** usaremos outros pacotes que já podemos instalar:
```{r, message=FALSE, warning=FALSE, eval = TRUE}
pacotes <- c(
"openair",
"lubridate",
"scales",
"rio"
)
easypackages::libraries(pacotes)
```
### Dados
Para este capítulo utilizaremos diversos conjuntos de dados para exemplificar o uso das principais ferramentas de manipulação de dados do *tidyverse*.
1. Dados climatológicos de precipitação e temperatura máxima anual de estações meteorológicas do [INMET](http://www.inmet.gov.br/portal/index.php?r=bdmep/bdmep) localizadas no estado do Rio Grande do Sul.
```{r, results='hide'}
clima_file_url <- "https://github.com/lhmet/adar-ufsm/blob/master/data/clima-rs.RDS?raw=true"
# dados de exemplo
clima_rs <- import(clima_file_url, format = "RDS")
clima_rs
```
```{r, echo = FALSE}
kable(clima_rs, align = "c")
```
2. Metadados das estações meteorológicas do [INMET](http://www.inmet.gov.br/portal/index.php?r=bdmep/bdmep) relacionadas a tabela de dados `clima_rs`.
```{r, results='hide'}
metadados_url <- "https://github.com/lhmet/adar-ufsm/blob/master/data/clima_rs_metadata_61_90.rds?raw=true"
# dados de exemplo
metadados_rs <- import(metadados_url, format = "RDS")
metadados_rs
```
```{r, echo = FALSE}
kable(metadados_rs, align = "c")
```
3. Um exemplo minimalista de dados referentes a séries temporais de precipitação anual observada em estações meteorológicas.
```{r, results='hide'}
prec_anual <- data.frame(
site = c(
"A001", "A001", "A002", "A002", "A002", "A003", "A803", "A803"
),
ano = c(2000:2001, 2000:2002, 2004, 2005, 2006),
prec = c(1800, 1400, 1750, 1470, 1630, 1300, 1950, 1100)
)
prec_anual
```
```{r, echo = FALSE}
kable(prec_anual, align = "c")
```
## *tibble*: um *quadro de dados* aperfeiçoado
Quadro de dados (*data frames*) são a unidade fundamental de armazenamento de dados retangulares no `r rblue`. O pacote **tibble** estende a classe *data frame* da base do `r rblue` com aperfeiçoamentos relacionados a impressão de dados (mais amigável e versátil), a seleção de dados e a manipulação de dados do tipo *factor*. O novo objeto é chamado de *tibble* e sua classe de `tbl_df`.
### Funcionalidades do *tibble*
Para ilustrar algumas vantagens do *tibble*, vamos usar o *data frame* `prec_anual`. A criação destes dados como *tibble* é feita com a função de mesmo nome do pacote: `tibble::tibble()`.
```{r}
prec_anual_tbl <- tibble(
site = c(
"A001", "A001", "A002", "A002", "A002", "A003", "A803", "A803"
),
ano = c(2000:2001, 2000:2002, 2004, 2005, 2006),
prec = c(1800, 1400, 1750, 1470, 1630, 1300, 1950, 1100)
)
```
O exemplo acima é ilustrativo, pois um *data frame* pode ser convertido em um *tibble* simplesmente com a função `tibble::as_tibble()`:
```{r}
prec_anual_tbl <- as_tibble(prec_anual)
prec_anual_tbl
```
Com o *tibble* acima, as principais diferenças entre um *tibble* e um *data frame* podem ser enfatizadas.
- quando impresso no console do R, o *tibble* já mostra a classe de cada variável.
- vetores caracteres não são interpretados como *factors* em um *tibble*, em contraste a `base::data.frame()` que faz a coerção para *factor* e não conserva o nome das variáveis. Este comportamento padrão pode causar problemas aos usuários desavisados em análises posteriores.
```{r}
str(data.frame("temp. do ar" = "18"))
```
- permite usar seus próprios argumentos prévios para definir variáveis durante a criação do *tibble*; veja o exemplo abaixo, onde a `int prec`(intensidade da precipitação) é baseada na razão da precipitação (`prec`) pelo número de dias no ano.
```{r}
prec_anual_tbl <- tibble(
site = c(
"A001", "A001", "A002", "A002", "A002", "A003", "A803", "A803"
),
ano = c(2000:2001, 2000:2002, 2004, 2005, 2006),
prec = c(1800, 1400, 1750, 1470, 1630, 1300, 1950, 1100),
"int prec" = prec / 365.25
)
prec_anual_tbl
```
- nunca adiciona nomes às linhas (`row.names`)
```{r}
# nomes das linhas de um data frame são carregados adiante
subset(prec_anual, ano == 2001)
# tibble não possui nome de linhas (rownames)
subset(prec_anual_tbl, ano == 2001)
```
- a impressão de um *tibble* mostra as dez primeiras linhas e a quantidade de colunas mostradas é ajustada ao tamanho da janela do console.
As opções de controle *default* da impressão de *tibbles* no console pode ser configuradas através da função de opções de configuração global do R:
```{r}
m <- 15
n <- 3
options(
tibble.print_max = m,
tibble.print_min = n
)
```
Com a configuração acima, será impresso no console do R `n = 3` linhas do *tibble* se ele tiver mais de `m = 15` linhas.
```{r}
nrow(clima_rs) > 15
# coersão do data.frame clima_rs para tibble
clima_rs_tbl <- as_tibble(clima_rs)
```
Para restaurar as opções *default* use:
```{r}
options(
tibble.print_max = NULL,
tibble.print_min = NULL
)
clima_rs_tbl
```
Uma alternativa útil para inspecionar mais detalhadamente os dados é a função `tibble::glimpse()`.
```{r}
glimpse(clima_rs)
```
Lembre-se também, da função `utils::View()` para visualizar os dados no RStudio.
```{r, eval = FALSE}
View(clima_rs)
```
Outros aspectos diferencias do *tibble* podem consultados na vinheta do referido pacote (`vignette("tibble")`).
## Restruturação de dados retangulares
> Até 80% do tempo da análise dados é dedicada ao processo de limpeza e preparação dos dados [@Dasu-Johnson, [New York Times 2014/08/18](https://www.nytimes.com/2014/08/18/technology/for-big-data-scientists-hurdle-to-insights-is-janitor-work.html)].
<!---
# references
#http://www.storybench.org/getting-started-with-tidyverse-in-r/
--->
### Dados arrumados
O conceito \"dados arrumados\" foi estabelecido por @Wickham2014 e representa uma forma padronizada de conectar a estrutura (formato) de um conjunto de dados a sua semântica (significado).
Dados bem estruturados servem para:
- fornecer dados propícios para o processamento e análise de dados por *softwares*;
- revelar informações e facilitar a percepção de padrões
Dados no \"formato arrumado\" atendem as seguintes regras para dados retangulares:
1. cada **variável** está em uma coluna
2. cada **observação** corresponde a uma linha
3. cada **valor** corresponde a uma célula
4. cada tipo de unidade observacional deve compor uma tabela
```{block, significados-obs, type='rmdnote'}
Como sinônimo de observações você pode encontrar os termos: registros, casos, exemplos, instâncias ou amostras dependendo da área de aplicação.
```
![Estrutura de dados padronizados](http://garrettgman.github.io/images/tidy-1.png)
Um exemplo de dados no formato arrumado é o *tibble* `prec_anual_tbl` mostrado abaixo:
```{r, echo = FALSE}
kable(
rename(
prec_anual_tbl,
"intensidade" = `int prec`
),
longtable = TRUE,
booktabs = TRUE,
#caption = "Exemplo de dados no formato arrumado.",
align = "c"
)
```
Os dados acima tem duas variáveis: precipitação (`prec`) e intensidade da precipitação (`intensidade`). As unidades observacionais são as colunas `site` e `ano`. A primeira unidade observacional informa o ponto de amostragem espacial e a segunda o ponto de amostragem temporal.
Uma **variável** contém todos valores que medem um mesmo atributo ao longo das unidades observacionais. Uma **observação** contém todos valores medidos na mesma unidade observacional ao longo dos atributos.
Cada **valor** (número ou caractere) pertence a uma variável e uma observação.
Exemplo de diferentes **tipos de unidades observacionais** são a tabela com a séries temporais dos elementos meteorológicos (exemplo acima) e a tabela com os metadados das estações de superfície que contém atributos das estações meteorológicas (`site` no exemplo acima), tais como: longitude, latitude, altitude, nome, município, estado e etc.
A estrutura de dados \"arrumados\" parece óbvia, mas na prática, dados neste formatos são raros de serem encontrados. As razões para isso incluem:
- quem projeta a coleta e o registro de dados nem sempre é aquele que gasta tempo trabalhando sobre os dados;
- a organização dos dados busca tornar o registro de dados o mais fácil possível;
Consequente, dados reais sempre precisarão ser arrumados. O primeiro passo é identificação das variáveis e das observações. O passo seguinte é resolver os seguintes problemas mais comuns:
- distribuir observações (que estão armazenadas nas colunas) ao longo das linhas
- distribuir variáveis (que estão armazenada nas linhas) ao longo das colunas
Essas duas operações são realizadas com as principais funções do pacote **tidyr**:
- `pivot_longer()`: para pivotar colunas ao longo das linhas (reunir \"variáveis\" nas linhas);
- `pivot_wider()`: para pivotar linhas ao longo das colunas (espalhar \"observações\" nas colunas)
<!---
#O formato de dados arrumado pode ser ideal para muitas operações no R que envolvem *data frames* (agregação, visualização gráfica, ajuste de modelos estatísticos), mas pode não ser a estrutura ideal para todos os casos.
--->
### Formatos de dados mais comuns
O pacote **tidyr** é a extensão do `r rblue` que fornece funcionalidades para reestruturar os dados entre diferentes formatos.
Os principais formatos de dados são:
- **dados longos**, são tabelas com mais valores ao longo das linhas; geralmente mistura variáveis com observações;
- **dados amplos**, são tabelas com valores mais distribuídos nas colunas, geralmente contém pelo menos uma unidade observacional misturada com variáveis;
#### Formato de dados longo {#formatos-dados}
Para exemplificar o formato de dados longo vamos partir dos \"dados arrumados\" do exemplo, `prec_anual_tbl`. Primeiro vamos renomear a variável `int prec` para `intensidade` para seguir um o padrão de nome das variáveis mais conveniente para o seu processamento no `r rblue`.
```{r}
prec_anual_tbl <- rename(
prec_anual_tbl,
"intensidade" = `int prec`
)
prec_anual_tbl
```
Vamos usar a função `tidyr::pivot_longer()` para reestruturar os dados `prec_anual_tbl` em uma nova tabela de dados que chamaremos `prec_anual_long`.
Na nova tabela, manteremos as colunas `site`, `ano` e teremos dois novos pares de variáveis: `variavel` e `valor`. Na coluna `variavel` pivotaremos as variáveis `prec` e `intensidade`. Na coluna `valor` pivotaremos os valores das variáveis `prec` e `intensidade`.
```{r}
prec_anual_long <- pivot_longer(
data = prec_anual_tbl,
cols = c(prec, intensidade), # ou c("prec", "intensidade"),
names_to = "variavel",
values_to = "medida"
)
prec_anual_long
# prec_anual_long <- gather(
# data = prec_anual_tbl,
# key = variavel,
# value = medida,
# prec, intensidade
# )
```
O código acima demonstra os principais argumentos requeridos pela função `gather`:
- `data = prec_anual_tbl`, o *quadro de dados* ou *tibble* que será reestruturado;
- `cols = c("prec", "intensidade")`, variáveis a serem pivotadas no formato longo;
- `names_to = variavel`, um vetor caractere com nome que nós escolhemos para dar à nova coluna que armazenará os dados nos **nomes das variáveis** dos dados de entrada (`data`).
- `values_to = medida`, um caractere com o nome que nós escolhemos para dar à nova coluna que armazenará os dados contidos nos valores das células;
As demais colunas dos dados (`site` e `ano`) serão mantidas inalteradas e seus valores serão repetidos quando necessário.
Como em outras funções dos pacotes do **tidyverse** você perceberá que alguns argumentos **não são especificados como caracteres** e sim como nomes (ou seja o nome da variável sem aspas), como aqueles usados quando definimos variáveis (p.ex.: `nome_var <- 10`). Os argumentos `names_to` e `values_to` podem ser especificados à gosto do usuário e não precisam ter relação com os dados existentes.
Se nós desejássemos que todas colunas do *quadro de dados* fossem reunidas em uma nova coluna `variavel` e os seus valores em uma nova coluna `valor`, isso poderia intuitivamente ser feito simplesmente especificando as variáveis de interesse por `everything()`[^selectores] no trecho de código anterior.
```{r, error= TRUE}
prec_anual_longo <- pivot_longer(
data = prec_anual_tbl,
cols = everything(),
names_to = "atributo",
values_to = "valor",
values_ptypes = list(site = 'numeric')
)
```
[^selectores]: Nós veremos mais sobre funções do tipo seletoras na seção de manipulação de dados.
Entretanto, como a variável site é do tipo caractere, ela não pode ser combinada com variáveis do tipo numérico. Então temos que transformar a variável `site` para numérico se isso for realmente necessário.
```{r}
prec_anual_tbl_num <- transform(
prec_anual_tbl,
site = parse_number(site)
)
prec_anual_tbl_num
```
A função `parse_number()` é uma função auxiliar do pacote **`readr`** para extrair números de um caractere.
```{r}
pivot_longer(
data = prec_anual_tbl_num,
cols = everything(),
names_to = "atributo",
values_to = "valor"
)
```
A tabela de dados resultante conterá todos os 32 pares de valores, formados pelas 4 colunas por 8 linhas, dos dados originais.
Se não forem especificados nomes para os argumentos `names_to` e `values_to` na chamada da função `tidyr::pivot_longer`, serão atribuídos os valores *default*: `name` e `value`.
```{r}
pivot_longer(
data = prec_anual_tbl_num,
cols = everything()
)
```
#### Formato de dados amplo
Utilizando os dados `meteo_long`, vamos reestruturá-lo no formato amplo para demostrar a funcionalidade da função `tidyr::pivot_wider()`. Esta função é complementar à `tidyr::pivot_longer()`.
```{r}
prec_anual_long
```
Nosso objetivo é então gerar uma nova tabela de dados reestruturada, de forma que os nomes das variáveis (contidos na coluna `variavel`) sejam pivotados em duas colunas. Estas colunas receberão os nomes `prec` e `intensidade` e serão preenchidas com os dados das células da coluna `medida`. Para fazer isso usamos o seguinte código:
```{r}
prec_anual_amplo <- pivot_wider(
data = prec_anual_long,
names_from = variavel,
values_from = medida
)
prec_anual_amplo
```
Esta operação serviu para colocar os dados originais (`prec_anual_long`) no formato \"arrumado\" (`prec_anual_amplo`).
### Funções adicionais do **tidyr**
Você pode unir duas colunas inserindo um separador entre elas com a função `tidyr::unite()`:
```{r}
(prec_anual_long_u <- unite(
data = prec_anual_long,
col = site_ano,
site, ano,
sep = "_"
))
```
Se ao contrário, você quer separar uma coluna em duas variáveis, utilize a função `tidyr::separate()`:
```{r}
separate(
data = prec_anual_long_u,
col = site_ano,
sep = "_",
into = c("site", "ano")
)
```
Para completar valores das variáveis para unidades observacionais faltantes podemos utilizar a função `tidyr::complete()`:
```{r}
prec_anual
prec_anual_comp <- complete(
data = prec_anual,
site, ano
)
prec_anual_comp
```
### Exercícios
```{r setup-ex-tidyr, include=FALSE}
#rm(list = ls())
knitr::opts_chunk$set(echo = TRUE,
comment = "#>",
prompt = FALSE,
collapse = TRUE,
include = FALSE)
```
**Pacotes necessários**
```{r, message=FALSE, warning=FALSE}
pcks <- c("rio", "tidyverse", "lubridate")
easypackages::libraries(pcks)
```
## Manipulação de dados
Com os dados arrumados, a próxima etapa é a manipulação dos dados. O pacote **dplyr** oferece um conjunto de funções que facilita as operações mais comuns para lidar com dados retangulares de uma forma bem pensada.
Os verbos fundamentais desta gramática de manipulação de dados são:
- `select()`, para selecionar variáveis;
- `filter()`, para filtrar observações;
- `arrange()`, para classificar variáveis;
- `mutate()`, para criar e transformar variáveis;
- `group_by()`, para agrupar observações;
- `summarise()`, para resumir os dados com medidas estatísticas descritivas;
Estes verbos possuem uma sintaxe consistente com uma sentença gramatical:
<p style="color:DodgerBlue; font-size:1.3em; font-weight: bold;text-align:center;"> `verbo(sujeito, complemento)` </p>
traduzindo de outra forma:
<p style="color:DodgerBlue; font-size:1.3em; font-weight: bold;text-align:center;"> `função(dados, z = x + y)` </p>
- o `verbo` é a função do **dplyr**;
- o `sujeito` (dados) é quem sofre a ação e é **sempre o primeiro argumento**, nomeado (`.data`);
- o `complemento` são expressões que podem ser usadas como argumentos (o que é representado pela reticência `...` no segundo argumento); isso ficará mais claro nos exemplos mais a frente;
```{block, note-pq-dplyr, type='rmdtip'}
Os verbos listados anteriormente possuem versões equivalentes na base do `r rblue`. Então, por que usar o *dplyr* ?
- é muito mais rápido de se aprender, com poucas funções (ou verbos) nomeadas intuitivamente;
- as funções do **dplyr** são mais rápidas (parte dos códigos são programados em C++);
- trabalha bem com dados arrumados e também com sistemas de banco de dados
- as funções foram projetadas para trabalharem juntas na solução diversos problemas de processamento de dados;
```
### Códigos como fluxogramas
<!--
In deciphering R code it is helpful to read from right to left and from inside to outside.
-->
A manipulação de dados requer uma organização apropriada do código. A medida que novas etapas do fluxo de trabalho vão sendo implementadas o código expande-se. As etapas vão sendo implementadas de forma sequencial, combinando funções que geram saídas que servirão de entrada para outras funções na cadeia de processamento.
Essa é justamente a ideia do operador *pipe* `%>%`: passar a saída de uma função para outra função como a entrada dessa função por meio de uma seqüência de etapas. O operador `%>%` está disponível no `r rblue` através do pacote [magrittr](https://cran.r-project.org/web/packages/magrittr/vignettes/magrittr.html).
<!---
#{block, pipe-linux, type='rmdtip'}
# O *pipe* pode ser familiar para quem já usou SO unix, onde o operador é representado por `|`. No comando linux abaixo listamos os arquivos com a extensão `.txt` e o resultado é passado como entrada ao comando `wc` com o argumento `-l` que conta quantas linhas tem a lista de arquivos. Neste caso o número de linhas corresponderá ao número de arquivos com a extensão `.txt`.
# `ls *.txt | wc -l`
--->
Os pacotes **tidyverse** integram-se muito bem com o `%>%`, por isso ele é automaticamente carregado com o **tidyverse**. Vamos ilustrar as vantagens de uso do %>% com exemplos a seguir.
#### Vantagens do %>%
O exemplo a baixo mostra uma aplicação simples do `%>%` para extrair a raiz quadrada de um número com a função `base::sqrt()`e a extração do segundo elemento de um vetor com a função `dplyr::nth()` (uma função alternativa aos colchetes `[]`).
```{r}
# chamada tradicional de uma função
sqrt(4)
nth(5:1, 2)
# chamada de uma função com %>%
4 %>% sqrt()
5:1 %>% nth(2)
```
Ambas formas realizam a mesma tarefa e com mesmo resultado e o benefício do `%>%` não fica evidente. Entretanto, quando precisamos aplicar várias funções as vantagens ficam mais óbvias.
No código abaixo tente decifrar o objetivo das operações no vetor x.
```{r, eval = TRUE}
x <- c(1, 3, -1, 1, 4, 2, 2, -3)
x
nth(sort(cos(unique(x)), decreasing = TRUE), n = 2)
```
Talvez com o código identado fique mais claro:
```{r, eval = FALSE}
nth( # 4
sort( # 3
cos( # 2
unique(x) # 1
),
decreasing = TRUE
),n = 2
)
```
O código acima está aninhando funções e isso leva a uma dificuldade de ler por causa da desordem. Para interpretá-lo precisamos fazer a leitura de dentro para fora:
1. mantém somente os valores únicos de x
2. calcula o cosseno do resultado de (1)
3. coloca em ordem decrescente o resultado de (2)
4. extrai o 2° elemento do resultado de (3)
Conclusão: o objetivo era obter o segundo maior número resultante do cosseno do vetor numérico x.
A versão usando pipe é:
```{r}
x %>%
unique() %>% # 1
cos() %>% # 2
sort(decreasing = TRUE) %>% # 3
nth(n = 2) # 4
```
Dessa forma, o código fica mais simples, legível e explícito. Por isso, daqui para frente, nós utilizaremos extensivamente o operador `%>%` para ilustrar os verbos do **dplyr** e suas combinações.
```{block, pipe-linux, type='rmdtip'}
No exemplo anterior nós introduzimos a função `dplyr::nth()`. Ela é equivalente ao operador colchetes `[` da base do R. Se `a <- 5:1` então as instruções abaixo produzem resultados equivalentes:
`a[2]; nth(a, 2)`
`#> [1] 4`
`#> [1] 4`
```
#### O operador `.` como argumento
Uma representação mais explícita do código usado na cadeia de funções acima, seria com a inclusão do operador `.` e os nomes dos argumentos das funções:
```{r}
x %>%
unique(x = .) %>% # 1
sort(x = ., decreasing = TRUE) %>% # 2
cos(x = .) %>% # 3
nth(x = ., n = 2) # 4
```
O tempo a mais digitando é compensado posteriormente quando o você mesmo futuramente tiver que reler o código. Essa forma enfatiza com o `.` que o resultado à esquerda é usado como entrada para função à direita do `%>%`.
Mas nem todas funções do `r rblue` foram construídas com os dados de entrada no primeiro argumento. Essa é a deixa para outra funcionalidade do `.` que é redirecionar os dados de entrada para a posição adequada naquelas funções. Uma função que se encaixa neste caso é a `base::grep()` que detecta uma expressão regular num conjunto de caracteres (*strings*).
```{r}
adverbs <- c("ontem", "hoje", "amanhã")
grep(
pattern = "h",
x = adverbs,
value = TRUE
)
```
O código acima seve para retornar os elementos do vetor `dias` que contenham a letra `h`. No entanto os dados de entrada da `base::grep()` são esperados no 2° argumento (`x`). Para redirecioná-los para essa posição dentro de uma cadeia de funções com `%>%`, colocamos o operador `.` no 2° argumento da função:
```{r}
adverbs %>%
grep(
pattern = "h",
x = .,
value = TRUE
)
```
<!---
# pipe forever?
# No. ver http://r4ds.had.co.nz/pipes.html#When%20not%20to%20use%20the%20pipe
--->
### Seleção de variáveis
```{r, ,echo = FALSE, out.width="20%", out.height="20%", fig.align='center', eval = TRUE}
knitr::include_graphics("images/dplyr-select.png")
```
Para selecionar somente variáveis de interesse em uma tabela de dados podemos usar a função `dplyr::select(.data, ...)`. Nos dados `clima_rs_tbl` se desejamos selecionar apenas as colunas `estacao` e `tmax` aplicamos a `dplyr::select()` com o 2° argumento listando as colunas que desejamos selecionar:
```{r}
select(clima_rs_tbl, estacao, tmax)
```
O resultado é um subconjunto dos dados originais contendo apenas as colunas nomeadas nos argumentos seguintes aos dados de entrada.
A função `dplyr::select()` possui funções auxiliares para seleção de variáveis:
```{r}
clima_rs_tbl %>%
# as variáveis entre uf e tmax
select(., uf:tmax) %>%
head(., n = 3)
clima_rs_tbl %>%
# todas variáveis menos as entre codigo:uf
select(., -(codigo:uf)) %>%
head(., n = 3)
clima_rs_tbl %>%
# ordem inversa das variáveis
select(., tmax:codigo) %>%
head(., n = 3)
clima_rs_tbl %>%
# nomes que contenham a letra "a"
select(., contains("a")) %>%
head(n = 3)
clima_rs_tbl %>%
# variáveis que iniciam com "c"
select(., starts_with("c")) %>%
head(., n = 3)
clima_rs_tbl %>%
# usando um vetor de caracteres
select(., any_of(c("estacao", "uf"))) %>%
head(., n = 3)
clima_rs_tbl %>%
# combinações
select(., -uf, ends_with("o")) %>%
head(., n = 3)
clima_rs_tbl %>%
# variáveis que inciam com letras minúsculas e com 4 caracteres
select(., matches("^[a-z]{4}$")) %>%
head(., n = 3)
# variáveis numéricas
clima_rs_tbl %>%
select(is.numeric)
```
O último exemplo usa uma expressão regular ([regex](https://pt.wikipedia.org/wiki/Express%C3%A3o_regular)). *Regex* é uma linguagem para descrever e manipular caracteres de texto. Há [livros sobre este assunto](http://aurelio.net/regex/guia/) e diversos [tutorias](https://stringr.tidyverse.org/articles/regular-expressions.html) sobre *regex* no R. Para saber mais sobre isso veja o capítulo sobre [strings](http://r4ds.had.co.nz/strings.html) do livro de @Wickham2017. Conhecendo o básico, você poupará tempo automatizando a formatação de caracteres de texto.
Veja mais funções úteis para seleção de variáveis em `?dplyr::select`.
### Seleção de observações
```{r, ,echo = FALSE, out.width="20%", out.height="20%", fig.align='center', eval = TRUE}
knitr::include_graphics("images/dplyr-filter.png")
```
A filtragem de observações geralmente envolve uma expressão que retorna valores lógicos ou as posições das linhas selecionadas (como a função `which()`).
A função `dplyr::filter()` permite filtrar observações de um *data frame* correspondentes a alguns critérios lógicos. Estes critérios podem ser passados um de cada vez ou com um operador lógico (e: `&`, ou: `|`). Veja abaixo alguns exemplos de filtragem de observações:
- linhas correspondentes ao `codigo` da estação 83936.
```{r}
clima_rs_tbl %>%
filter(codigo == 83936)
```
- linhas da variável `estacao` que contenham o vetor caractere `litoraneas`.
```{r}
litoraneas <- c("Torres",
"Guaporé")
clima_rs_tbl %>%
filter(estacao %in% litoraneas)
```
- observações com `tmax` acima de 10% da média
```{r}
filter(clima_rs_tbl, tmax > 1.1*mean(tmax))
```
- observações com `tmax` e `prec` acima de suas médias
```{r}
clima_rs_tbl %>%
filter(
tmax > mean(tmax),
prec > mean(prec)
)
# equivalente a
#clima_rs %>%
# filter(tmax > mean(tmax) & prec > mean(prec))
```
- observações cuja variável `estacao` tem a palavra \"Sul\"
```{r}
# estações com "Sul" no nome
clima_rs_tbl %>%
filter(str_detect(estacao, "Sul"))
```
```{block, sringr, type='rmdtip'}
O exemplo acima é mais uma operação com caracteres onde foi usada a função `stringr::str_detect()` para detectar os elementos da variável do tipo caractere que contenham o termo \"Sul\". O pacote **stringr** [@Wickham-stringr] fornece funções para casar padrões de caracteres de texto e os nomes das funções são fáceis de lembrar. Todos começam com `str_` (de string) seguido do verbo, p.ex.:
`str_replace_all(`
` string = c("abc", "lca"),`
` pattern = "a",`
` replacement = "A"`
`)`
`#> [1] "Abc" "lcA"`
```
A seleção de observações também pode ser baseada em índices passados para função `dplyr::slice()` que retorna o subconjunto de observações correspondentes. Abaixo vejamos alguns exemplos de filtragem de linhas baseada em índices ou posições:
```{r}
# linhas 2 e 4
clima_rs_tbl %>%
slice(., c(2, 4))
# última linha
clima_rs_tbl %>%
slice(., n())
# exlui da última à 3a linha
clima_rs_tbl %>%
slice(., -(n():3))
# linhas com tmax > 26
clima_rs_tbl %>%
slice(., which(tmax > 26))
# linhas com tmax mais próxima a média de tmax
clima_rs_tbl %>%
slice(., which.min(abs(tmax - mean(tmax))))
```
### Reordenando dados
```{r, ,echo = FALSE, out.width="20%", out.height="20%", fig.align='center', eval = TRUE}
knitr::include_graphics("images/dplyr-arrange.png")
```
As vezes é útil reordenar os dados segundo a ordem (crescente ou decrescente) dos valores de uma variável. Por exemplo, os dados `clima_rs_tbl` podem ser arranjados em ordem decrescente da precipitação anual, conforme abaixo.
```{r}
clima_rs_tbl %>%
arrange(., desc(prec)) %>%
head(., n = 3)
```
A função `dplyr::arrange()` por padrão ordena os dados em ordem crescente. A função `dplyr::desc()` ordena os valores da variável em ordem descendente.
Os dados ordenados pela `tmax`, ficam da seguinte forma:
```{r}
clima_rs_tbl %>%
arrange(., tmax) %>%
head(., n = 3)
```
### Criando e renomeando variáveis
```{r, ,echo = FALSE, out.width="50%", out.height="55%", fig.align='center', eval = TRUE}
knitr::include_graphics("images/dplyr-mutate-rename.png")
```
Uma nova variável pode ser adicionada aos dados através da função `dplyr::mutate()`. A `tmax` expressa em Kelvin pode ser adicionada aos dados `clima_rs_tbl`, com:
```{r}
clima_rs_tbl %>%
# tmax em Kelvin
mutate(., tmaxK = tmax + 273.15) %>%
# só as colunas de interesse
select(., contains("tmax")) %>%
# 3 primeiras linhas
head(., n = 3)
```
Podemos renomear variáveis com a função `dplyr::rename()`.
```{r}
clima_rs_tbl %>%
rename(.,
"id" = codigo,
"site" = estacao,
"temp_max" = tmax,
"precip" = prec
) %>%
head(., n = 3)
```
Podemos sobrescrever variáveis e recodificar seus valores, conforme o exemplo abaixo. A variável `site` será corrigida, de forma os valores iguais a "A803" sejam substituídos por "A003".
```{r}
prec_anual_corr <- prec_anual %>%
mutate(
site = recode(site, A803 = "A003")
)
tail(prec_anual_corr, n = 4)
```
Podemos preencher os valores faltantes de uma variável por um valor prescrito, por exemplo baseado na média de outras observações, ou nos valores prévios, ou posteriores. Variáveis podem ser derivadas das variáveis sendo criadas dentro da `dplyr::mutate()`.
```{r}
# preenchendo prec faltante pela média
prec_anual_comp %>%
mutate(.,
prec = replace_na(prec,
mean(prec, na.rm = TRUE)
),
ndias = ifelse(ano %% 4 == 0,
366,
365),
# intensidade de ndias, criada na linha acima
intensidade = prec / ndias
)
prec_anual_comp %>%
# preenche com a observação prévia
fill(prec, .direction = "down")
prec_anual_comp %>%
# preenche com a observação posterior
fill(prec, .direction = "up")
```
### Agregando observações
```{r, ,echo = FALSE, out.width="40%", out.height="50%", fig.align='center', eval = TRUE}
knitr::include_graphics("images/dplyr-summarise-count.png")
```
A função `dplyr::summarise()` (ou `dplyr::sumarize()`) agrega valores de uma variável e os fornece para uma função que retorna um único resultado. O resultado será armazenado em um `data frame`.
Por exemplo, qual a `prec` média anual do RS?
```{r}
clima_rs_tbl %>%
summarise(
.,
prec_med = mean(prec)
)
```
Se você só quer o valor (ou o vetor), ao invés de um `data frame`, pode usar a função `dplyr::pull()`:
```{r}
clima_rs_tbl %>%
summarise(