-
Notifications
You must be signed in to change notification settings - Fork 0
/
07-manip-vetores.Rmd
1851 lines (1243 loc) · 60.8 KB
/
07-manip-vetores.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
# Manipulação de Vetores {#manip-vectors}
```{r setup, include = FALSE}
rm(list = ls())
pcks <- c("knitr", "pander", "htmlTable")
easypackages::libraries(pcks)
opts_chunk$set(
prompt = FALSE,
cache = FALSE,
fig.path = "images/",
comment = "#>",
collapse = TRUE
)
source("R/utils.R")
```
Neste capítulo veremos como manipular vetores, incluindo:
- como nomear vetores
- realizar cálculos entre vetores
- gerar sequências
- entender a indexação de vetores
- lidar com dados faltantes, nulos e duplicados
- usar as funções para cálculos móveis
Em algumas seções deste capítulos usaremos funções dos pacotes do grupo [tidyverse](https://www.tidyverse.org/), como o [ggplot2](https://ggplot2.tidyverse.org/) e [dplyr](https://dplyr.tidyverse.org/). Para carregá-los basta digitar:
```{r, message=FALSE, warning=FALSE, error=FALSE}
library(tidyverse)
```
## Propriedades
+ `typeof()` para descobrir o tipo de dado
+ `length()` para descobrir o tamanho de um tipo de dado
+ `attributes` (informações acionais específicas do dado), entre eles o atributo mais comum está o `names()`.
### Nomeando vetores
As 3 formas equivalentes mais comuns de criar vetores com nomes são demostradas abaixo com um exemplo de dados mensais de precipitação.
+ Durante a criação, com a função `c()` incluindo os nomes nos argumentos
```{r nv1, message=FALSE}
# vetor de chuva mensal para um dado ano
prec <- c(
jan = 300,
fev = 150,
mar = 210,
abr = 12,
mai = 0,
jun = 0,
jul = 12,
ago = 22,
set = 100,
out = 120,
nov = 10,
dez = 280
)
```
+ Modificando um vetor com a função `names()<-`
```{r nv2}
prec <- c(300, 200, 210, 12, 0, 0, 12, 22, 100, 120, 10, 280)
meses <- c("jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez")
names(prec) <- meses
prec
```
+ Criando um vetor modificado
```{r nv3}
prec <- setNames(
object = c(300, 200, 210, 12, 0, 0, 12, 22, 100, 120, 10, 280),
nm = c("jan", "fev", "mar", "abr", "mai", "jun", "jul", "ago", "set", "out", "nov", "dez")
)
prec
```
Nomes não podem ser repetidos entre os elementos, porque a seleção de um subconjunto do vetor baseada nos nomes retornará somente o primeiro elemento que tiver nome repetido.
Embora não faça muito sentido, nem todos elementos precisam ter nomes. A saída da função `names()` retornará um vetor caractere vazio (\"\") para aqueles elementos sem nomes especificados.
```{r chunk75}
(meses <- c(jan = 1, fev = 2, 3:12))
names(meses)
```
Quando nenhum nome é especificado, `names()` retornará `NULL`[^mais-sobre-null].
```{r}
names(1:12)
```
[^mais-sobre-null]: Nós conheceremos mais detalhes sobre o `NULL` na sessão \@ref(dados-nulos).
Para remover os nomes de um vetor, podemos usar a função `unname()` ou `names() <- NULL`.
```{r chunk76, message=FALSE}
prec_clim <- c(230, 205, 160, 100, 60, 30, 40, 60, 110, 165, 200, 220)
names(prec_clim) <- names(prec)
prec_clim
unname(prec_clim)
names(prec_clim) <- NULL
prec_clim
```
Nas próximas seções frequentemente usaremos os vetores `prec` e `prec_clim`. É importante então contextualizar essas variáveis. A variável `prec` consiste na precipitação mensal observada em um ano qualquer em um dado local. A variável `prec_clim` refere-se aos valores esperados de precipitação mensal[^normais] (médias de pelo menos 30 anos) do mesmo local.
[^normais]: Também conhecidos como **normais climatológicas** de precipitação de um local.
## Atributos
Nós podemos adicionar atributos a um vetor, como por exemplo alguma informação sobre os valores daquela variável. A variável `prec` possui um atributo (`names`). A função `attributes()` lista qualquer atributo de uma variável. Vamos criar uma variável para mostrar como podemos adicionar um atributo a um vetor.
```{r}
temp <- c(27, 23, 21, 18, 19, 28)
attributes(temp)
```
Podemos adicionar um atributo chamado `metadados` à `temp` e fornecer um vetor caractere com a função de atribuição de atributo `attr()<-`
```{r}
attr(temp, "metadados") <- "dados obtidos em www.inmet.gov.br, acesso em 10/10/2010"
temp
```
Algumas funções carregarão este atributo adiante, mas outras não, conforme exemplo a seguir.
```{r}
(temp_inc <- temp + 1)
(temp_inc <- c(temp_inc, 18))
```
Há situações de uso válido deste recurso, mas inicialmente é melhor não confiar nele.
## Operações com vetores {#oper-vect}
Como o `R` é uma linguagem vetorizada, as operações são aplicadas a cada elemento do vetor automaticamente, sem a necessidade de laços (ou *loopings*) ao longo do vetor. Esta é uma das grandes vantagens do `r rblue`.
Operações aritméticas podem ser aplicadas diretamente entre vetores.
```{r chunk78, message=FALSE}
# desvios da prec em relação a média climatológica
prec - prec_clim
# anomalia em % relativa
prec/prec_clim * 100
# transformação boxcox da prec com alpha = 0.335
((prec^0.335 - 1)/0.335)
# cte^intervalo
mean(prec)^(1/2:5)
```
Uma peculiaridade do `r rblue` é o tratamento de operações com vetores de tamanhos diferentes. O vetor menor é reciclado, de forma que seus elementos sejam repetidos em ordem até atingirem o tamanho do vetor mais longo envolvido na operação.
```{r chunk711, message=FALSE}
# velocidades em m s-1
(vel_ms <- c(1.5, 0.3, 1.4, 2.0))
# fator de conversão para km h-1
fator_conv <- 3.6
vel_ms * fator_conv
# equivalência
fator_conv <- c(3.6, 3.6, 3.6, 3.6)
vel_ms * fator_conv
```
A constante `fator_conv = 3.6` nesse caso é reciclada 4 vezes (tamanho do vetor `vel_ms`) e então multiplicada por cada elemento de `vetor_dbl`. Por isso os resultados no código acima são idênticos. Essa funcionalidade de fazer um vetor do mesmo tamanho de outro é conhecida como **reciclagem**. Se o vetor mais longo não tem tamanho múltiplo do mais curto, o `r rblue` realiza a operação com uma mensagem de aviso.
```{r}
1:10 * 1:2
1:10 * 1:3
```
A reciclagem é um recurso útil, mas também perigoso. Seu código pode ficar mais elegante ou gerar resultados inesperados.
Operações aritméticas podem ser feitas com vetores lógicos, como nos exemplos abaixo:
```{r}
FALSE - TRUE
prec_clim >= 100
(prec_clim >= 100) * 1:12
```
### Comparações
Vetores lógicos resultam da comparação de números ou caracteres. A Tabela \@ref(tab:oper-logic) apresenta os principais operadores lógicos para comparações.
```{r oper-logic, echo = FALSE, warning=FALSE}
# <a name="tab-oper-logic"></a>
oper <- c("<", "<=", ">", ">=", "==", "!=", "!x", "x | y", "x & y", "isTRUE(x)", "%in%")
desc <- c("menor que", " menor ou igual a", "maior que", "maior ou igual", "idêntico", "diferente", "não é x (negação)", "x ou y", "x e y", "teste se x é verdadeiro", "está contido em")
oper_logic <- data.frame(
Operador = oper,
Descrição = desc,
stringsAsFactors = FALSE
)
kable(oper_logic, caption = "Operadores Lógicos", align = "c")
```
Este conjunto de operadores permite diversas comparações entre vetores, por exemplo:
- quais meses de `prec` foram abaixo do normal?
```{r}
prec
prec_clim
prec - prec_clim < 0
```
O operador `%in%` serve para verificar se um vetor está contido parcial ou totalmente em outro vetor.
```{r }
# operador está contido em
c(200, 150, 100) %in% prec
# 2:4 são elementos de x?
is.element(c(200, 150, 100), prec)
```
Nos exemplos acima, vimos como buscar os os elementos de um vetor para apenas uma condição. Entretanto, frequentemente precisamos testar mais condições, ou seja, combinar comparações. Por exemplo, para condições do tipo:
- $0 < prec \leq 100$
- $prec < 50$ ou $prec \geq 150$
precisamos usar os operadores relacionais:
- `&` e `&&` (\"e"\)
- `|` e `||` (\"ou"\)
```{r}
# prec entre 0 e 100 mm
prec > 0 & prec <= 100
# prec abaixo de 50 e acima de 150 mm
prec < 50 | prec >= 150
```
A ordem das operações pode ser controlada por parênteses. Os operadores `&` e `|` são vetorizados (retornam vetores de mesmo tamanho que os vetores testados).
A forma dupla (`&&` ou `||`) compara somente um elemento de cada lado, enquanto a forma normal (`&` e `|`), compara cada elemento dos vetores em cada lado.
```{r chunk7290, message=FALSE}
a <- c(1, 1, 0, 1)
b <- c(2, 1, 0, 1)
# forma normal verifica cada elemento de a e cada elemento de b
a == 1 & b == 1
# forma dupla verifica somente o primeiro elemento de a e o primeiro elemento de b
# retornando somente um resultado
a == 1 && b == 1
```
```{r chunk72901, message=FALSE , echo=FALSE, out.width=200}
oper <- c("a", "b", "a==1", "b==1", "a == 1 & b == 1", "a == 1 && b == 1")
desc <- data.frame(
a,
b,
a == 1,
b == 1,
a == 1 & b == 1,
a == 1 && b == 1
)
names(desc) <- oper
desc[2:nrow(desc), 6] <- ""
pander(desc, caption = "Demonstração da diferença entre & e &&.")
```
Podem haver mais que duas condições a serem testadas. As condições podem ser combinadas usando múltiplos `&` ou `|`. As diferentes condições podem ser agrupadas por parênteses assim como feito nas operações matemáticas.
#### Testes de igualdade
A comparação de igualdade no `r rblue` pode ser meio confusa devido as forma de armazenamento diferentes dos números.
```{r}
0.6 - 0.3
0.9 - 0.6
0.3 == 0.3
```
Tudo normal, mas ao comparar operações com valores decimais, você pode se surpreender:
```{r}
(0.6 - 0.3) == (0.9 - 0.6)
```
Isso ocorre por imprecisão no final da parte decimal que pode ser arrendondada incorretamente. Isso não acarreta problema na maioria dos cálculos. Para evitar esse problema é melhor comparar os resultados usando a função `all.equal()`.
```{r}
all.equal(
target = 0.6 - 0.3,
current = 0.9 - 0.6
)
```
A `all.equal()` inclui uma tolerância na comparação ($1,5\times10^{-8}$) fazendo com aquela imprecisão seja ignorada. Para mais detalhes consulte `?all.equal`.
### Funções `any` e `all`
Estas funções fornecem um único valor (vetor lógico de tamanho 1) para resumir ou descrever o resultado da condição aplicada ao vetor.
```{r chunk715, message=FALSE }
vetor <- c(0, 1, -1, -2, 3, 5, -5)
all(vetor < 0) # todas as posições são maiores que 0 ?
any(vetor > 0) # alguma posição é maior que 0?
```
- `all()` verifica se a condição avaliada é válida para todos elementos de um vetor;
- `any()` verifica se a condição avaliada é válida para pelo menos um dos elementos de um vetor;
## Sequências
Vimos nas seções anteriores que é muito simples criar sequências de números inteiros com o operador `:`. Nesta seção veremos outras formas de gerar sequências, como uma sequência de números reais e sequências de números repetidos.
### Sequências de números inteiros
Os dois pontos (`:`) são uma maneira muito fácil de gerar uma sequência de números igualmente espaçados por 1. Você especifica um número inicial e um número final e o `R` produzirá todos os números inteiros entre eles, incluindo os dois números. Isso funciona mesmo para números negativos ou para valores decrescentes.
```{r chunk716, message=FALSE}
(ddm <- 1:31)
typeof(ddm)
# sequencia de inteiros decrescente
(si_dec <- 10:-10)
typeof(si_dec)
```
### Sequências de números reais
A função `seq()`pode ser usada para gerar sequências tanto de números reais como inteiros.
No código abaixo são geradas uma sequência crescente e uma decrescente, ambas igualmente espaçadas por 3.
```{r seq1}
seq(from = 1, to = 10, by = 3)
seq(from = 10, to = 1, by = -3)
```
Para sequências decrescentes o argumento `by` (\"por\") deve ser negativo.
A saída da `seq()` vai sempre incluir o n° inicial (passado no argumento `from` - \"de\"), mas nem sempre incluirá o n° final (passado no argumento `to` - \"até\"). Se sua sequência está aumentando por um argumento `by` que é par (ímpar) e o argumento `to` também é par (ímpar), não incluirá o valor do argumento `to` no resultado (Tabela \@ref(tab:seqs-by)). Quando `to` e `by` diferem o valor de `to` fará parte da sequência de saída.
```{r seqs-by, eval = TRUE, echo = FALSE}
tbl_seqs_by <- tibble::tibble(
`'from'` = 1,
`'to'` = c(10, 10, 11, 11),
`'to' é par?` = `'to'` %% 2 == 0,
`'by'` = rep(c(2, 3), times = 2),
`'by' é par?` = `'by'` %% 2 == 0,
`sequência` = mapply(base::seq,
from = `'from'`,
to = `'to'`,
by = rep(c(2, 3), times = 2)
),
`resultado inclui 'to'` = lapply(
base::seq_along(`'to'`),
function(i) {
`'to'`[i] %in% `sequência`[[i]]
}
)
)
knitr::kable(tbl_seqs_by,
caption = "Sequências com argumentos ímpares e pares.",
align = "c"
)
```
Ao invés de usar o argumento `by`, podemos especificar um valor para o argumento `length.out` (\"tamanho de saída\") para produzir um vetor com tantos números, igualmente espaçados, entre os valores `from` e `to`.
```{r chunk718, message=FALSE }
seq(from = 1, to = 10, length.out = 20)
```
O `length.out = 20` no código acima permite gerar 20 números igualmente espaçados entre 1 e 10.
### Repetições
Algumas vezes precisamos repetir certos valores, o que pode ser feito com a função `rep()`. O argumento `times` especifica o número de vezes para repetir o `x`.
```{r}
rep(x = 1:2, times = 4)
```
O argumento `each` especifica o número de vezes para repetir cada elemento de `x`.
```{r}
rep(x = 1:2, each = 3)
```
Os argumentos podem ser combinados.
```{r}
rep(x = 1:2, times = 4, each = 3)
```
No caso acima, `x` primeiro foi repetido 4 vezes e depois cada elemento foi repetido 3 vezes.
Quando argumento `times` é um vetor de mesmo tamanho que `x`, cada um de seus valores será usado para repetir tantas vezes o respectivo elemento de `x`.
```{r}
rep(x = 1:2, times = 4:3)
```
<!--
AULA-6 encerrou aqui
-->
## Indexação de vetores {#index-vetores}
Os elementos de um vetor são indexados e para acessá-los usamos a notação de índices do `r rblue`. Para extrair ou filtrar elementos de um vetor usamos o operador colchetes **`[ ]`**, seguindo a sintaxe:
<p style="color:DodgerBlue; font-size:1.3em; font-weight: bold;text-align:center;"> `vetor[indices]` </p>
onde **`indices`** representa o vetor com os índices dos elementos da variável `vetor` a serem selecionados. O operador **`[`** quando aplicado a um vetor retornará sempre um vetor.
Para acessar partes um elemento de um vetor o vetor `indices` dentro dos colchetes pode ser especificado de diferentes formas:
- por posições (vetor numérico)
- por nomes (vetor de caracteres)
- por comparações, testes ou condições (vetor lógico)
### Indexação por vetores numéricos
#### Positivos
Para extrairmos a precipitação de janeiro e dezembro do vetor `prec` podemos usar o seguinte código:
```{r chunk721, message=FALSE }
# vetor com as posições dos meses de janeiro e dezembro
c(1, length(prec))
# acesso aos valores localizados nas posições 1 e 12
prec[c(1, length(prec))]
```
Passando um vetor numérico entre os colchetes retorna a parte do vetor contendo os elementos daquelas posições.
Similarmente a precipitação dos meses de inverno (Junho, Julho e Agosto) podem ser selecionadas usando um vetor definido com os índices das posições daqueles meses:
```{r chunk723, message=FALSE }
inds_jja <- 6:8
# vetor de chuva JJA
prec[inds_jja]
```
```{block, reposicionamento, type='rmdtip'}
O reposicionamento dos elementos de um vetor pode ser feito pela especificação da ordem dos índices. Par ordenar os elementos na ordem dezembro, Janeiro e Fevereiro indexamos da seguinte maneira:
`prec[c(12, 1, 2)]`
A inversão da ordem dos elementos pode ser feita com a indexação:
`prec[length(prec):1]`
A função `rev()` economiza tempo de digitação de código para realizar esta mesma ação:
`rev(prec)`
```
#### Negativos
O acesso aos dados de precipitação de janeiro e dezembro do vetor `prec` poderia ser feita uma lógica complementar. Poderíamos selecionar todos elementos de `prec` exceto aqueles entre Fevereiro (posição 2) e Novembro (posição 11). Esta frase poderia ser transcrita em código `R`, simplesmente como `-(2:11)`. O sinal `-` precedendo o vetor numérico, exclui o acesso aquelas posições quando usado entre o operador **`[`**.
```{r chunk724, message=FALSE }
prec[-(2:11)]
```
Analogamente, os meses de inverno poderiam ser selecionados com:
```{r}
prec[-c(1:5, 9:12)]
```
### Indexação por nomes
A seleção de partes e um vetor pode ser feita também usando os nomes de seus elementos. As precipitações de janeiro e dezembro poderiam ser extraídas usando os nomes daqueles elementos:
```{r}
prec[c("jan", "dez")]
```
Assim como as precipitações de inverno.
```{r}
prec[c("jun", "jul", "ago")]
```
### Indexação por vetores lógicos
Vamos criar um vetor lógico e usá-lo para a seleção com um vetor lógico dos elementos de `prec` para Janeiro e Dezembro.
```{r chunk725, message=FALSE}
inds_log <- c(
TRUE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, TRUE
)
prec[inds_log]
```
Somente os elementos de `inds_log` correspondentes a `TRUE` foram selecionados.
Vetores lógicos são muito úteis quando aproveitamos a funcionalidade de **coerção**. Imagine que você queira extrair de `prec` o primeiro elemento, mas o segundo não, o terceiro elemento sim, o quarto não e assim sucessivamente. Essa seleção intercalada pode ser simplesmente feita com:
```{r chunk727, message=FALSE }
inds_log <- c(TRUE, FALSE)
prec[inds_log]
```
Uma forma mais prática de filtrar vetores é por comparações. Por exemplo, quais valores de precipitação foram acima de 80 mm?
```{r chunk728, message=FALSE}
inds_prec_alta <- prec > 80
prec[inds_prec_alta]
```
Vimos que a filtragem consiste em extrair elementos de um vetor que satisfaça uma ou várias condições. Entretanto, em alguns casos, o interesse está nas posições do vetor que atendem a condição (onde ela é verdadeira). Nós podemos localizar essas ocorrências usando a função `which()`. Por exemplo, qual a posição dos elementos do vetor `inds_prec_alta` que são verdadeiros?
```{r}
which(inds_prec_alta)
```
A função `which()` converte um vetor lógico em numérico, somente os índices em que a condição é `TRUE`.
A utilidade da `which()` é mais evidente quando usada para, por exemplo, sabermos qual o mês do 4° caso mais chuvoso.
```{r}
which(inds_prec_alta)[4]
names(which(inds_prec_alta)[4])
# ou
names(prec)[which(inds_prec_alta)[4]]
```
```{block, which-more, type='rmdtip'}
A resultado da `which()` é um vetor numérico e portanto equivale a indexação numérica. Então a seleções abaixo são equivalentes:
`prec[which(inds_prec_alta)]`
`prec[inds_prec_alta]`
Quando é melhor usar uma ou outra opção?
Note que o resultado de `which(inds_prec_alta)` armazena somente os índices que satisfazem a condição, enquanto que o resultado de `inds_prec_alta` é um vetor lógico de mesmo tamanho que `prec`. Então, se estiver trabalhando com **big data** (p.ex.: um vetor com milhões de elementos) em termos de eficiência de uso da memória a `which()` é melhor opção.
```
```{block, which-max-min, type='rmdimportant'}
Para localizar valores extremos em um vetor podemos usar as funções `which.max()` e `which.min()` que fornecem respectivamente, a posição do valor máximo e mínimo no vetor.
Elas são versões eficientes dos códigos `which(x == max(x))` e `which(x == min(x))`. Contudo, há uma diferença entre elas que pode ser verificada pela comparação dos resultados das instruções:
`which.min(prec)`
`which(prec == min(prec))`
A primeira seleciona o primeiro índice para o qual `prec` tem seu mínimo (5° elemento), enquanto a segunda retorna todos os índices correspondentes ao mínimo (5° e 6° elemento).
```
## Substituição de elementos de um vetor {#replace-vect}
Podemos substituir os valores de um vetor usando os mesmos esquemas de indexação vistos na seção anterior. A sintaxe geral para substituir elementos de um vetor por novos valores é:
<p style="color:DodgerBlue; font-size:1.3em; font-weight: bold;text-align:center;"> `vetor[indices] <- novos_valores` </p>
Vamos fazer uma cópia do vetor `prec` para então alterá-lo, fazendo substituição de seus elementos usando as diferentes formas de indexação.
```{r}
(prec_alt <- prec)
```
#### Por posições
suponha que você precisa substituir os valores de precipitação dos meses de inverno por valores corrigidos.
```{r chunk732, message=FALSE}
inds_jja
prec_alt[inds_jja] <- c(NA, 21, 42)
prec
prec_alt
```
#### Por nomes
Suponha que os valores de precipitação de janeiro e dezembro foram atualizados para 250 e 208, respectivamente. Esta alteração pode ser com o código abaixo.
```{r chunk733, message=FALSE}
prec_jd_corr <- c(250, 208)
prec_alt[c("jan", "dez")] <- prec_jd_corr
prec
prec_alt
```
#### Por comparação
Imagine que você precisa substituir os valores de `prec` que ficaram em torno de $\pm10 \%$ da média mensal climatológica pelos valores climatológicos.
Vamos primeiro determinar os desvios relativos (em %) em relação as médias climatológicas:
```{r}
# limiar em % da normal climatológica
limiar <- 10
desvios <- prec - prec_clim
# anomalias relativas em %
(anom_perc <- abs(desvios)/prec_clim * 100)
```
Então substituímos os casos com baixo desvio pela precipitação climatológica.
```{r}
# meses com prec em torno de +-10% da média climatol.
prec[anom_perc <= 10]
# substituição pela prec mensal climatol.
prec[anom_perc <= 10] <- prec_clim[anom_perc <= 10]
prec
```
A função `abs()` determina o valor absoluto ou módulo de um vetor.
Uma alternativa bastante útil para substituir valores de um vetor usando comparações é a **função vetorizada** **`ifelse()`**. A mesma operação realizada no trecho de código anterior poderia ser feita com `ifelse()` da seguinte forma:
```{r, eval = FALSE}
prec <- ifelse(ano_perc <= 10, prec_clim, prec)
```
```{r}
prec
```
<!---
Uma exemplo é sua aplicação para preencher as falhas no vetor `prec_alt` por seus valores climatológicos.
```{r}
prec_alt_comp <- ifelse(
test = is.na(prec_alt), # condição: é faltante?
yes = prec_clim, # se verdadeira: preenche com prec_clim
no = prec_alt # se falsa: mantém prec_alt
)
prec_alt_comp
```
--->
## Lidando com dados faltantes
Dados faltantes (`NA`s) são inevitáveis e em qualquer processamento de dados reais nós precisamos determinar se existem dados faltantes e a quantidade de observações válidas. É importante também, saber o efeito que eles tem nos cálculos, as funcionalidades para identificá-los e substituí-los se necessários.
Vamos substituir alguns valores da `prec_alt` por `NA` para poder tratar de dados faltantes usando as diferentes funcionalidades que o `r rblue` oferece para isso.
```{r}
prec_alt[c(3, 4, 11)] <- NA
prec_alt
```
### Identificação e remoção de `NA`s
Para identificar `NA`s em um vetor, a função específica para isso é a `is.na()`.
```{r}
is.na(prec_alt)
```
Também podemos usá-la aninhada com a função `which()` para obter os índices dos elementos faltantes.
```{r}
which(is.na(prec_alt))
```
Novos usuários do R tentam identificar dados faltantes com a expressão:
```{r}
prec_alt == NA
```
O que produzirá somente `NA`s mesmo que o vetor testado possua algum `NA`. Isso ocorre pela regra de qualquer operação com `NA`s resulta em `NA`s.
Para verificar se há algum dado faltante em um vetor usamos a função `anyNA()` e para quantificar o total de observações faltantes combinamos as expressões `sum()` e `is.na()`:
```{r}
anyNA(prec_alt)
sum(is.na(prec_alt))
```
A remoção dos elementos faltantes de um vetor é moleza. É só combinar o operador negação `!` e `is.na()` por indexação lógica:
```{r}
prec_alt[!is.na(prec_alt)]
# outra forma equivalente
#prec_alt[-which(is.na(prec_alt))]
```
Uma alternativa mais sofisticada é a função `na.omit()`. Ela não só remove os valores faltantes, mas como também guarda a localização dos dados faltantes. Esta informação é armazenada na lista de atributos do vetor.
```{r}
prec_alt_sem_falt <- na.omit(prec_alt)
attributes(prec_alt_sem_falt)
```
As posições originais dos dados faltantes descartados podem ser obtidas com:
```{r}
attr(
x = prec_alt_sem_falt,
which = "na.action"
)
```
Quando trabalhamos com vetores grandes que contenham várias falhas é útil saber a posição da sequência de dados consecutivos válidos mais longa. A função `na.contiguous()` retornará somente elementos daquela sequência.
```{r}
prec_alt_val_long <- na.contiguous(prec_alt)
prec_alt_val_long
```
### Indexação com `NA`s
Suponha que queremos extrair um conjunto de elementos de `prec_clim` baseado em `inds_na`.
```{r}
prec_alt > 220
```
O interesse é extrair os valores de `prec_clim` quando a `prec_alt` superou 220 mm. A expressão para essa seleção é:
```{r}
prec_clim[prec_alt > 220]
```
o resultado da filtragem foi um vetor com o resultado da condição de prec_clim para qual `prec_alt > 220` e também `NA`s. Isto é um resultado que provavelmente ninguém deseja.
Se nós queremos extrair os valores de `prec_clim` para os quais `prec_alt` **não é faltante** e **também superior a 220** nós devemos usar a seguinte expressão:
```{r}
prec_clim[!is.na(prec_alt) & prec_alt > 220]
```
A moral da história aqui é que na prática quando você tem `NA`s em índices (ou seja, nos valores de qualquer vetor dentro do colchetes) o `r rblue` pode retornar algo diferente do que era esperado.
Uma função para filtragem de dados que é capaz de dar conta disso mais prontamente é função `subset()` (que pode ser traduzida como *subconjunto*) que recebe os dados no primeiro argumento (`x`) e a expressão lógica no segundo (argumento `subset` de mesmo nome da função).
```{r}
subset(
x = prec_clim,
subset = prec_alt > 220
)
```
### Efeito de `NAs` em funções
Na seção \@ref(NAs) vimos que qualquer operação com `NA` resulta em `NA`. Algumas funções úteis merecem ser enfatizadas quando usadas em vetores com dados faltantes.
A função `range()` retorna a amplitude de variação dos valores em um vetor.
```{r}
range(prec_alt)
```
Como `prec_alt` possui dados faltantes ela retornará `NA`. Assim como várias outras funções matemáticas básicas no `r rblue` a função `range()` permite especificar o argumento `na.rm = TRUE` para calcular o resultado após omitir os valores faltantes.
```{r}
range(prec_alt, na.rm = TRUE)
```
Logo, `prec_alt` varia de um mínimo `r min(prec_alt, na.rm = TRUE)` a um máximo de `r max(prec_alt, na.rm = TRUE)`.
Diversas funções tem essa funcionalidade, entre elas as mais usadas para estatísticas descritivas, como:
```{r}
# prec máx. mensal
max(prec_alt, na.rm = TRUE)
# pŕec min mensal
min(prec_alt, na.rm = TRUE)
# prec total anual
sum(prec_alt, na.rm = TRUE)
# prec média
mean(prec_alt, na.rm = TRUE)
# mediana da prec
median(prec_alt, na.rm = TRUE)
# desvio padrão
sd(prec_alt, na.rm = TRUE)
# variância
var(prec_alt, na.rm = TRUE)
```
A função `summary()` fornece um resumo estatístico de uma variável, incluindo: mínimo, 1° quartil, mediana, média, 3° quartil, máximo e o número de casos faltantes (se aplicável).
```{r}
summary(prec_alt)
```
## Dados Nulos (`NULL`) {#dados-nulos}
O `NULL` é um tipo especial de dado no `r rblue`. Ele é um vetor de tamanho zero.
```{r}
vetor_nulo1 <- NULL
vetor_nulo1
length(vetor_nulo1)
```
Um vetor nulo também pode ser definido com:
```{r}
vetor_nulo2 <- c()
vetor_nulo2
```
Note que um vetor ser nulo não significa que ele não exista. Ou seja, a atribuição de `NULL` a uma variável não apaga a variável de seu ambiente de trabalho. A existência de uma variável pode ser verificada com a função `exists()`, na qual o argumento `x` deve ser passado como caractere.
```{r}
exists(x = "vetor_nulo1")
```
Como o `NULL` é um vetor vazio, seu uso explícito dentro de um vetor não conta. Assim, qualquer operação com `NULL` resulta em um vetor vazio.
```{r}
(vetor_elem_nulo <- c(1, 2, NULL, 4))
length(vetor_elem_nulo)
vetor_elem_nulo + NULL
```
Em algumas situações você pode querer anular um atributo de um vetor, como os nomes. Eventualmente até mesmo o próprio vetor.
```{r}
prec
names(prec) <- NULL
prec
prec <- NULL
prec
```
## Dados duplicados
Dados frequentemente pode ter valores duplicados ou repetidos e dependendo da aplicação isso pode causar problemas nos resultados. Portanto é importante detectar e remover essas ocorrências. O `r rblue` oferece algumas funções convenientes para detectar dados duplicados.
Mas antes, vamos criar um vetor de datas com alguns dias repetidos para então mostrar as funcionalidades disponíveis.
```{r}
datas <- seq(
from = as.Date("2017-01-10"),
to = as.Date("2017-01-10") + 10,
by = "day"
)
datas <- c(
datas[1:6], NA,
datas[7:length(datas)],
datas[length(datas)],
datas[5:6]
)
datas
```
A função `duplicated()` detecta onde ocorrem valores repetidos.
```{r}
duplicated(datas)
```
Ela retorna um vetor lógico mostrando quais elementos são duplicados. Neste exemplo os últimos 3 elementos. Este resultado pode ser usado para remover os valores repetidos:
```{r}
# datas únicas: sem valores duplicados
datas[!duplicated(datas)]
```
Alternativamente, há função `unique()` para remover valores repetidos de um vetor:
```{r}
unique(datas)
```
## Dados ordenados
Duas operações comuns em análise de dados são a ordenação e a classificação dados de um vetor.
A função `sort()` arranja os dados de um vetor numérico em ordem crescente ou descrescente (se argumento for especificado como `decreasing = TRUE`). Se o vetor for de caracteres, o arranjo segue a ordem alfabética dando precedência às letras em minúsculo.
```{r}
sort(prec_alt)
sort(prec_alt, decreasing = TRUE)
```
```{r}
sort(names(prec_alt))
```
A ordem de classificação de cada elemento de um vetor numérico é obtida com a função `order()`:
```{r}
prec_alt
order(prec_alt)
```
O resultado indica que o 5º elemento de `prec_alt` é o menor valor e o 1º elemento é o de maior valor. Isso pode ser facilmente verificado passando este resultado na indexação da `prec_alt`.
```{r}
# equivalente a sort()
prec_alt[order(prec_alt)]
```
Nota-se então, que por padrão na saída da `order()` os elementos faltantes são colocados nas últimas posições (no exemplo: 3, 4, 6, 11). Para remover os casos faltantes especificamos o argumento `na.last = NA`.
```{r}
order(prec_alt, na.last = NA)
```
## Funções móveis úteis
Se queremos obter um valor que leve em consideração todos os valores anteriores e o valor atual, podemos usar funções da família **cum{fun}()**, como a **`cumsum()`** para somar valores à medida que avançamos na sequência. Esta operação é conhecida como soma cumulativa, total móvel ou soma móvel.
Vamos obter a soma cumulativa da série da precipitação mensal abaixo.
```{r}
# serie de com 2 anos de prec mensal
prec <- c(
230, 205, 160, 100, 60, 30,
40, 60, 110, 165, 200, 220,
250,200, 210, 12, 0, 30,
21, 42, 100, 120, 10, 208
)
prec
# meses de prec como datas
dts <- seq(
from = as.Date("2010-01-01"),
by = "month",
length.out = length(prec)
)
dts
prec_ac <- cumsum(prec)
prec_ac
```
A relação entre essas duas variáveis pode ser melhor compreendida pelo gráfico da Figura \@ref(fig:plot-cumsum).
```{r plot-cumsum, ref.label='plot-cumsum', echo = FALSE, fig.align='center', fig.cap="Visualização da soma acumulada. A precipitação será representada por barras e a precipitação acumulada até o mês decorrido como linha. Nós abordaremos os recursos para visualização gráfica na seção **Visualização de dados**.", out.width='90%'}
#library(ggplot2)
# gráfico
graf <- qplot(
x = dts,
y = prec,
geom = c("col"),
ylim = range(c(prec, prec_ac))
) +
# ajuste dos labels das datas (eixo x)
scale_x_date(
name = "meses",
date_breaks = "2 months",