-
Notifications
You must be signed in to change notification settings - Fork 7
/
03-r-base.Rmd
1802 lines (1142 loc) · 63.3 KB
/
03-r-base.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
# R Básico {#r-base}
```{r, include=FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
fig.align = "center"
)
tabela <- function(tab) {
knitr::kable(tab)
}
```
Introduziremos aqui os principais conceitos de programação em R. Indicamos a leitura deste capítulo a quem nunca teve contato com uma linguagem de programação ou a quem gostaria de entender um pouco melhor a estrutura de objetos, funções e classes do R.
Os tópicos discutidos aqui são especialmente importantes para entendermos o que é um *data frame*, a nossa base de dados dentro do R, e quais operações estão sendo realizadas por trás das cortinas quando estivermos filtrando suas linhas ou modificando suas colunas. Também são importantes para começarmos a criar as nossas próprias funções, o que deixa nossos códigos muito mais organizados, eficientes e *compartilháveis*.
## Pedindo Ajuda
Na linguagem `R` é possível fazer bastante coisa à base da tentativa e erro. Além disso, grande parte do conhecimento é escalável, isto é, aprender a utilizar uma função é meio caminho andado para aprender todas as outras funções que operam de forma semelhante^[Essa ideia é um dos princípios por trás do `tidyverse`.].
No entanto, a intuição não é infalível, e recorrentemente vamos precisar de ajuda para rodar alguma função ou descobrir como fazer alguma tarefa no R. Felizmente, a comunidade R é bem ativa e existem vários lugares para buscar respostas. Nesta seção, vamos apresentar algumas dessas maneiras.
```{r r-base-1, fig.cap=Sys.getenv("cap_alisson_horst"), echo=FALSE}
knitr::include_graphics("assets/img/r-base/code_hero_rstats.png")
```
No R, há quatro principais entidades para se pedir ajuda:
- Help/documentação do R
- Google
- Stack Overflow
- Coleguinha
A busca por ajuda é feita preferencialmente, mas não necessariamente, na ordem acima.
### Documentação do R
A documentação do R serve para você aprender a usar uma determinada função. Se você não sabe o que é uma função, não se preocupe. Discutiremos esse tópico nas Seções \@ref(objetosFuncoes) e \@ref(maisFuncoes).
Você pode acessar a documentação de uma função^[Bases de dados presentes em pacotes também têm documentação, e geralmente é possível encontrar o significado de cada variável nela. Por exemplo, `help(mtcars)`.] através de dois comandos: `?nome_da_funcao` ou `help(nome_da_funcao)`. Por exemplo, para acessar a documentação da função `mean`, fazemos:
```{r, eval=FALSE}
?mean
# ou
help(mean)
```
Algumas dicas:
1. Leia a seção *Usage* para ter noção de como usar a função.
2. Os parâmetros da função estão descritos em *Arguments*.
3. Os exemplos no final são particularmente úteis.
4. Caso essa função não atenda às suas necessidades, a seção *See Also* sugere funções relacionadas.
Alguns pacotes possuem tutoriais de uso mais completos. Esses textos são chamados de `vignettes` e podem ser acessados com a função `vignette(package = 'nomeDoPacote')`. Por exemplo, `vignette(package = 'dplyr')`.
### Google
Há uma comunidade gigantesca de R gerando diariamente uma infinidade de conteúdos e discussões. Não raramente, você irá encontrar discussões sobre o seu problema simplesmente o descrevendo no Google. Pesquisas em inglês aumentam consideravelmente a chance de encontrar uma resposta.
Quando você recebe um erro na tentativa de rodar algum código no R e não sabe o que está errado, uma boa estratégia é pesquisar a mensagem de erro no Google. Essa deve ser sua primeira tentativa para resolver o problema. Repare na imagem abaixo o 'r' adicionado na busca. Isso ajuda bastante a encontrar uma solução.
```{r error = TRUE}
log("5")
```
```{r r-base-2, echo=FALSE, fig.align='center', out.width="795pt", out.height="267pt"}
knitr::include_graphics("assets/img/r-base/ajuda_google.png")
```
### Stack Overflow
O [Stack Overflow](http://stackoverflow.com/) e o [Stack Overflow em Português](http://pt.stackoverflow.com/) são sites de Pergunta e Resposta amplamente utilizados por todas as linguagens de programação, e o R é uma delas. Nos EUA, chegam até a usar a reputação das pessoas dentro da plataforma como diferencial no currículo!
Provavelmente o Google lhe indicará uma dessas quando você estiver procurando ajuda. E quando todas as fontes possíveis de ajuda falharem, o Stack Overflow lhe dará o espaço para **criar sua própria pergunta**.
**Um ponto importante**: como fazer uma *boa pergunta* no Stack Overflow?
No site, existe um tutorial com uma lista de boas práticas, [que se encontra aqui](http://pt.stackoverflow.com/help/how-to-ask). Resumindo, as principais dicas são
- fazer perguntas concisas;
- fazer perguntas específicas;
- ter mente aberta; e
- ser gentil.
Porém, no caso do R, há outro requisito que vai aumentar muito sua chance de ter uma boa resposta: **exemplinho minimal e reprodutível**.
- Ser **minimal**: usar bancos de dados menores e utilizar pedaços de códigos apenas suficientes para apresentar o seu problema. Não precisa de banco de dados de um milhão de linhas e nem colocar o seu código inteiro para descrever a sua dúvida.
- Ser **reprodutível**: o seu código deve rodar fora da sua máquina. Se você não fornecer uma versão do seu problema que rode (ou que imite seu erro), as pessoas vão logo desistir de te ajudar. Por isso, nunca coloque bancos de dados que só você tem acesso. Use bancos de dados que já vem no R ou disponibilize um exemplo (possivelmente anonimizado) em `.csv` na web para baixar. E se precisar utilizar funções de algum pacote, especifique os pacotes que você usou.
<!-- ### R Markdown -->
<!-- O R Markdown é um tipo de documento especial que contém tanto textos em *markdown* quanto *chunks* de códigos em R, tudo escrito no mesmo lugar. -->
<!-- O *markdown* nada mais é do que um documento de texto com alguns padrões básicos de formatação, como negrito, itálico, títulos, subtítulos, itens e referências cruzadas. Já os *chunks* são pedaços de códigos em R encapsulados por três crases (```). Os códigos são executados sempre que o documento é processado. -->
<!-- ```{r, echo=FALSE} -->
<!-- cat("```{r} -->
<!-- isto é um chunk. -->
<!-- ```") -->
<!-- ``` -->
<!-- > Este site foi escrito em R Markdown. Toda vez que aparecer exemplos de código de R, havia um chunk no .Rmd original. -->
<!-- Para produção de relatórios, o R Markdown possui algumas vantagens, como: -->
<!-- 1. **Simplicidade e foco**. Permite ao usuário o foco na análise e não na formatação do documento. -->
<!-- 1. **Versátil**. Pode ser utilizado para gerar documentos em `LaTeX`, `Word`, `HTML` e apresentações em `beamer`, `pptx` e `HTML`. Pode ainda gerar sites, livros, dissertações de mestrado e até mesmo dashboards interativos. -->
<!-- 1. **Reprodutível**. O R Markdown nada mais é que um arquivo de texto. Além disso, ele tenta te obrigar a fazer o documento mais autocontido possível. Assim, um documento `.Rmd` é fácil de compartilhar e de ser utilizado pelo receptor. Lembre-se, o receptor pode ser o futuro você! Vale enfatizar que a reprodutibilidade é considerada como um dos princípios fundamentais da ciência. Então, só de usar R Markdown, você já está colaborando com o método científico. :) -->
<!-- 1. **Flexível**. É possível configurar e criar *templates* de análises para quaisquer tipos de aplicações e clientes. Os textos podem ser parametrizados por números que variam de versão para versão, mensalmente, por exemplo, tudo escrito somente em R. -->
<!-- Criar um R Markdown novo no RStudio é fácil. Clique no botão de criar arquivo e selecione R Markdown. -->
<!-- ```{r echo=FALSE, fig.align='center'} -->
<!-- knitr::include_graphics(rep("assets/img/r-base/criar_rmarkdown.png")) -->
<!-- ``` -->
<!-- Para detalhes sobre como utilizar o R Markdown, leia [esta seção do R4DS](http://r4ds.had.co.nz/r-markdown.html) e [o tutorial do RStudio](http://rmarkdown.rstudio.com/lesson-1.html). -->
## R como calculadora
O papel do **Console** no R é executar os nossos comandos. Ele avalia o código que passamos para ele e devolve a saída correspondente --- se tudo der certo --- ou uma mensagem de erro --- se o seu código tiver algum problema.
Vamos começar com um exemplo simples:
```{r}
1 + 1
```
Nesse caso, o nosso comando foi o código `1 + 1` e a saída foi o valor `2`.
> **Quando compilamos?** Quem vem de linguagens como o C ou Java espera que seja necessário compilar o código em texto para o código das máquinas (geralmente um código binário). No R, isso não é necessário. O R é uma linguagem de programação dinâmica que interpreta o seu código enquanto você o executa.
Tente agora jogar no console a expressão: `2 * 2 - (4 + 4) / 2`.
Pronto! Você já é capaz de pedir ao R para fazer qualquer uma das quatro operações aritméticas básicas. A seguir, apresentamos uma lista resumindo como fazer as principais operações no R.
```{r}
# adição
1 + 1
# subtração
4 - 2
# multiplicação
2 * 3
# divisão
5 / 3
# potência
4 ^ 2
# resto da divisão de 5 por 3
5 %% 3
# parte inteira da divisão de 5 por 3
5 %/% 3
```
Repare que as operações e suas precedências são mantidas como na matemática, ou seja, divisão e multiplicação são calculadas antes da adição e subtração. E os parênteses nunca são demais!
Uma outra forma de executar uma expressão é escrever o código em um **script**, deixar o cursor em cima da linha e usar o atalho `Ctrl + Enter`. Assim, o comando é enviado para o **Console**, onde é diretamente executado. Essa operação é chamada de **avaliar**, **executar** ou **rodar** o código.
Se você digitar um comando incompleto, como `5 + `, e apertar `Enter`, o R mostrará um `+`, o que não tem nada a ver com a adição da matemática. Isso significa que o R está esperando você enviar **mais** algum código para completar o seu comando. Termine o seu comando ou aperte `Esc` para recomeçar.
```
> 5 -
+
+ 5
[1] 0
```
Se você digitar um comando que o R não reconhece, ele retornará uma mensagem de erro.
NÃO ENTRE EM PÂNICO!
Ele só está avisando que não conseguiu interpretar o comando. Você pode digitar outro comando normalmente em seguida.
```
> 5 % 2
Error: unexpected input in "5 % 2"
> 5 ^ 2
[1] 25
```
### Exercícios {-}
**1.** Qual a diferença entre o R e o RStudio?
**2.** Podemos usar o RStudio sem o R? E o R sem o RStudio?
**3.** Precisamos compilar nossos códigos de R?
**4.** Calcule o número de ouro no R. Dica: o número de ouro é dado pela expressão $\frac{1 + \sqrt{5}}{2}$.
**5.** Por que é preferível escrevermos sempre o nosso código no *script* e não no *Console*?
## Objetos e funções {#objetosFuncoes}
O R te permite salvar valores dentro de um **objeto**. Um objeto é simplesmente um nome que guarda um valor. Para criar um objeto, utilizamos o operador `<-`.
No exemplo abaixo, salvamos o valor `1` em `a`. Sempre que avaliarmos o objeto `a`, o R vai devolver o valor 1.
```{r}
# Salvando `1` em `a`
a <- 1
# Avaliando o objeto `a`
a
```
Existem algumas regras para dar nomes aos objetos. A mais importante é: o nome deve começar com uma letra^[Ou com um ponto.]. O nome pode conter números, mas não pode começar com números. Você pode usar pontos `.` e underlines `_` para separar palavras.
```{r, eval = FALSE}
# Permitido
x <- 1
x1 <- 2
objeto <- 3
meu_objeto <- 4
meu.objeto <- 5
# Não permitido
1x <- 1
_objeto <- 2
meu-objeto <- 3
```
**Atenção!**
O R **diferencia letras maiúsculas e minúsculas**, isto é, `b` é considerado um objeto diferente de `B`. Rode o exemplo abaixo e observe que dois objetos diferentes são criados no **Environment**.
```{r}
b <- 2
B <- 3
b
B
```
O objeto mais importante para cientistas de dados é, claro, a base de dados. No R, uma base de dados é representada por objetos chamados de *data frames*. Na próxima seção, vamos entender o que são esses objetos.
Enquanto objetos são *nomes* que guardam *valores*, funções no R são *nomes* que guardam um **código de R**. A ideia é muito simples: sempre que você rodar uma função, o código que ela guarda será executado e um resultado nos será devolvido.
A sintaxe para usar uma função é a seguinte:
```{r, eval = FALSE}
nome_da_funcao(arg1, arg2, argn)
```
Entre parênteses, após o nome da função, temos o que chamamos de *argumentos*. Uma função pode ter qualquer número de argumentos e eles são sempre separados por vírgula.
Basicamente, uma função recebe seus argumentos, executa uma ação sobre ou a partir deles e devolve um resultado. Por exemplo
```{r}
sum(1, 2)
```
A função `sum()` recebeu os argumentos `1` e `2`, somou os dois valores e devolveu o resultado dessa operação: o valor `3`.
Falaremos mais sobre funções na Seção \@ref(maisFuncoes).
### Exercícios {-}
**1.** Qual a diferença entre os códigos abaixo?
```{r, eval = FALSE}
# Código 1
33 / 11
# Código 2
divisao <- 33 / 11
```
**2.** Multiplique a sua idade por 12 e salve o resultado em um objeto chamado `idade_em_meses`. Em seguida, multiplique esse objeto por 30 e salve o resultado em um objeto chamado `idade_em_dias`.
**3.** Por que o nome `meu-objeto` não pode ser utilizado para criar um objeto? O que significa a mensagem de erro resultante?
```{r, error=TRUE}
meu-objeto <- 1
```
## Data frames
Os *data frames* são de extrema importância no R, pois são os objetos que guardam os nossos dados. Eles são equivalentes a uma tabela do SQL ou uma planilha do Excel.
A principal característica de um *data frame* é possuir linhas e colunas^[Você pode construir um *data frame* vazio, com 0 linha e 0 coluna. No entanto, a *estrutura* de linhas e colunas estará presente.]. Veja o exemplo abaixo:
```{r}
mtcars
```
O `mtcars` é um *data frame* nativo do R que contém informações sobre diversos modelos de carros. Ele possui 32 linhas e 11 colunas^[A primeira "coluna" representa apenas o *nome* das linhas (modelo do carro), não é uma coluna da base. Repare que ela não possui um nome, como as outras. Essa estrutura de nome de linha é própria de *data frames* no R. Se exportássemos essa base para o Excel, por exemplo, essa coluna não apareceria.]. Se você quiser saber mais sobre o `mtcars`, veja a documentação dele rodando `?mtcars` no **Console**.
Nos próximos capítulos, os *data frames* serão o nosso principal objeto de estudo. Aprenderemos a selecionar, criar e modificar colunas, filtrar e ordenar linhas, juntar dois *data frames* e, a partir deles, construiremos gráficos e ajustaremos modelos.
Mas, da mesma forma que é muito mais fácil aprendermos a fritar um ovo após entendermos o que é o fogo, uma frigideira e um ovo, vamos estudar nas próximas seções quais são as estruturas que formam os *data frames* e como manipulá-las.
## Classes
A classe de um objeto é muito importante dentro do R. É a partir dela que as funções e operadores conseguem saber exatamente o que fazer com um objeto.
Por exemplo, podemos somar dois números, mas não conseguimos somar duas letras (texto):
```{r, error=TRUE}
1 + 1
"a" + "b"
```
O operador `+` verifica que `"a"` e `"b"` não são números (ou que a classe deles não é numérica) e devolve uma mensagem de erro informando isso.
Observe que para criar texto no R, colocamos os caracteres entre aspas. As aspas servem para diferenciar *nomes* (objetos, funções, pacotes) de *textos* (letras e palavras). Os textos são muito comuns em variáveis categóricas e são popularmente chamados de *strings* no contexto de programação.
```{r}
a <- 10
# O objeto `a`, sem aspas
a
# A letra (texto) `a`, com aspas
"a"
```
Para saber a classe de um objeto, basta rodarmos `class(nome-do-objeto)`.
```{r}
x <- 1
class(x)
y <- "a"
class(y)
class(mtcars)
```
As classes mais básicas dentro do R são:
- *numeric*
- *character*
- *logical*
> Geralmente serão utilizados como sinônimos:
>
> - número, valor real, *numeric*, *double*
> - texto, string, *character*, caracteres
> - lógico, *logical*, booleano, valor TRUE/FALSE
Veja alguns exemplos:
```{r eval=FALSE}
# numeric
1
0.10
0.95
pi
# characters
"a"
"1"
"positivo"
# logical
TRUE
FALSE
```
Um objeto de qualquer uma dessas classes é chamado de **objeto atômico**.
Esse nome se deve ao fato de essas classes não se misturarem, isto é, para um objeto ter a classe `numeric`, por exemplo, todos os seus valores precisam ser numéricos.
Mas como atribuir mais de um valor a um mesmo objeto? Para isso, precisamos criar **vetores**.
### Exercícios
**1.** Guarde em um objeto chamado `nome` uma *string* contendo o seu nome completo.
**2.** Guarde em um objeto chamado `cidade` o nome da cidade onde você mora. Em seguida, guarde em um objeto chamado `estado` o nome do estado onde você mora. Usando esses objetos, resolva os itens abaixo:
- **a.** Utilize a função `nchar()` para contar o número de caracteres em cada cada string.
- **b.** Interprete o resultado do seguinte código:
```{r, eval = FALSE}
paste(cidade, estado)
```
- **c.** Interprete o resultado do seguinte código:
```{r, eval = FALSE}
paste(cidade, estado, sep = " - ")
```
- **d.** Desafio. Como você reproduziria o mesmo resultado do item (c) sem utilizar o argumento `sep`?
- **e.** Qual a diferença entre as funções `paste()` e `paste0()`?
## Vetores
Vetores são estruturas muito importantes dentro R. Em especial, pensando em análise de dados, precisamos estudá-los pois cada coluna de um *data frame* será representada como um vetor.
Vetores no R são apenas **conjuntos indexados de valores**. Para criá-los, basta colocar os valores separados por vírgulas dentro de um `c()`.
```{r}
vetor1 <- c(1, 5, 3, -10)
vetor2 <- c("a", "b", "c")
vetor1
vetor2
```
Os objetos `vetor1` e `vetor2` são vetores.
Uma maneira fácil de criar um vetor com uma sequência de números é utilizar o operador `:`.
```{r}
# Vetor de 1 a 10
1:10
# Vetor de 10 a 1
10:1
# Vetor de -3 a 3
-3:3
```
Quando dizemos que vetores são conjuntos *indexados*, isso quer dizer que cada valor dentro de um vetor tem uma **posição**. Essa posição é dada pela ordem em que os elementos foram colocados no momento em que o vetor foi criado. Isso nos permite acessar individualmente cada valor de um vetor.
Para isso, colocamos o índice do valor que queremos acessar dentro de colchetes `[]`.
```{r}
vetor <- c("a", "b", "c", "d")
vetor[1]
vetor[2]
vetor[3]
vetor[4]
```
Você também pode colocar um conjunto de índices dentro dos colchetes, para pegar os valores contidos nessas posições:
```{r}
vetor[c(2, 3)]
vetor[c(1, 2, 4)]
```
Essa operação é conhecida como *subsetting*, pois estamos pegando subconjuntos de valores de um vetor.
Se você tentar acessar uma posição do vetor que não existe, ele retornará `NA`, indicando que esse valor não existe. Discutiremos o que são `NA`'s na Seção \@ref(valoresEspeciais).
```{r}
vetor[5]
```
Um vetor só pode guardar um tipo de objeto e ele terá sempre a mesma classe dos objetos que guarda. Para saber a classe de um vetor, rodamos `class(nome-do-vetor)`.
```{r}
vetor1 <- c(1, 5, 3, -10)
vetor2 <- c("a", "b", "c")
class(vetor1)
class(vetor2)
```
Se tentarmos misturar duas classes, o R vai apresentar o comportamento conhecido como **coerção**.
```{r}
vetor <- c(1, 2, "a")
vetor
class(vetor)
```
Veja que todos os elementos do vetor se transformaram em texto. Agora temos um vetor com o texto `"1"`, o texto `"2"` e o texto `"a"`. Como um vetor só pode ter uma classe de objeto dentro dele, classes mais fracas serão sempre reprimidas pelas classes mais fortes. Como regra de bolso: caracteres serão sempre a classe mais forte. Então, sempre que você misturar números e texto em um vetor, os números virarão texto.
Falaremos bastante de coerção nas próximas seções e capítulos, trazendo exemplos de quando ela ajuda e de quando ela atrapalha.
Você também pode fazer operações com vetores.
```{r}
vetor <- c(0, 5, 20, -3)
vetor + 1
```
Ao rodarmos `vetor1 + 1`, o R soma `1` em cada um dos elementos do vetor. O mesmo acontece com qualquer outra operação aritmética.
```{r, eval=FALSE}
vetor - 1
vetor / 2
vetor * 10
```
Você também pode fazer operações que envolvem mais de um vetor:
```{r}
vetor1 <- c(1, 2, 3)
vetor2 <- c(10, 20, 30)
vetor1 + vetor2
```
Neste caso, o R irá alinhar os dois vetores e somar elemento a elemento. Esse tipo de comportamento é chamado de **vetorização**. Isso pode ficar um pouco confuso quando os dois vetores não possuem o mesmo tamanho. Tente adivinhar qual será a saída do código a seguir:
```{r}
vetor1 <- c(1, 2)
vetor2 <- c(10, 20, 30, 40)
vetor1 + vetor2
```
Embora estejamos somando dois vetores de tamanho diferentes, o R não devolve um erro (o que parecia ser a resposta mais intuitiva). O R alinhou os dois vetores e, como eles não possuíam o mesmo tamanho, o primeiro foi repetido para ficar do mesmo tamanho do segundo. É como se o primeiro vetor fosse na verdade `c(1, 2, 1, 2)`. Esse comportamento é chamado de **reciclagem**.
Embora contra-intuitiva, a reciclagem é muito útil no R graças a um caso particular muito importante. Quando somamos `vetor + 1` no nosso primeiro exemplo, o que o R está fazendo por trás é transformando o `1` em `c(1, 1, 1, 1)` e realizando a soma vetorizada `c(0, 5, 20, -3) + c(1, 1, 1, 1)`. Isso porque o número `1` nada mais é do que um vetor de tamanho 1, isto é, `1` é igual a `c(1)`.
Usaremos esse comportamento no R o tempo todo e é muito importante a reciclagem para termos certeza de que o R está fazendo exatamente aquilo que gostaríamos que ele fizesse.
Um outro caso interessante de reciclagem é quando o comprimento dos vetores não são múltiplos um do outro.
```{r}
vetor1 <- c(1, 2, 3)
vetor2 <- c(10, 20, 30, 40, 50)
vetor1 + vetor2
```
Neste caso, duas coisas aconteceram:
1. O R realizou a conta, repetindo cada valor do primeiro vetor até que os dois tenham o mesmo tamanho. No fundo, a operação realizada foi `c(1, 2, 3, 1, 2) + c(10, 20, 30, 40, 50)`.
2. Como essa operação é ainda menos intuitiva e raramente desejada, o R devolveu um aviso dizendo que o comprimento do primeiro vetor maior não é um múltiplo do comprimento do vetor menor.
### Exercícios {-}
**1.** Guarde em um objeto a sequência de números de 0 a 5 e resolva os itens abaixo.
- **a.** Use subsetting para fazer o R devolver o primeiro número dessa sequência. Em seguida, faça o R devolver o último número da sequência.
- **b.** Multiplique todos os valores do vetor por -1. Guarde o resultado em
um novo objeto chamado `vetor_negativo`.
**2.** Crie um vetor com o nome de três `frutas`, guarde em um objeto chamado frutas e resolva os itens abaixo.
- **a.** Utilize a a função `length()` para verificar o tamanho do vetor.
- **b.** Inspecione a saída de `paste("eu gosto de", frutas)` e responda se o tamanho do vetor mudou.
**3.** O que é reciclagem? Escreva um código em R que exemplifique esse comportamento.
**4.** O que é coerção? Escreva um código em R que exemplifique esse comportamento.
**5.** Por que a coerção pode ser um problema na hora de importarmos bases de dados para o R?
**6.** Use a função `sum()` para somar os valores de 1 a 100.
**7.** Considere o vetor booleano a seguir:
```{r}
dolar_subiu <- c(TRUE, TRUE, FALSE, FALSE, TRUE, FALSE, TRUE)
```
Este vetor tem informação de uma semana (7 dias, começando no domingo) indicando se o dólar subiu (TRUE) ou não subiu (FALSE) no respectivo dia. Interprete o resultado dos códigos abaixo:
- **a.** `length(dolar_subiu)`
- **b.** `dolar_subiu[2]`
- **c.** `sum(dolar_subiu)`
- **d.** `mean(dolar_subiu)`
## Testes lógicos
Poder fazer qualquer tipo de operação lógica é um dos motivos pelos quais programar nos deixar mais eficientes. Dê bastante atenção a elas, pois usaremos comparações lógicas o tempo todo!
Uma operação lógica nada mais é do que um teste que retorna **verdadeiro** ou **falso**. No R (e em outras linguagens de programação), esses dois valores recebem uma classe especial: `logical`.
O **verdadeiro** no R vai ser representado pelo valor `TRUE` e o **falso** pelo valor `FALSE`. Esses nomes no R são **reservados**, isto é, você não pode chamar nenhum objeto de *TRUE* ou *FALSE*.
```{r, eval = FALSE}
TRUE <- 1
## Error in TRUE <- 1 : invalid (do_set) left-hand side to assignment
```
Checando a classe desses valores, vemos que são lógicos^[Também conhecidos como valores binários ou booleanos]. Eles são os únicos possíveis valores dessa classe.
```{r}
class(TRUE)
class(FALSE)
```
Agora que conhecemos o `TRUE` e `FALSE`, podemos explorar os teste lógicos. Começando pelo mais simples: vamos testar se um valor é igual ao outro. Para isso, usamos o operador `==`.
```{r}
# Testes com resultado verdadeiro
1 == 1
"a" == "a"
# Testes com resultado falso
1 == 2
"a" == "b"
```
Também podemos testar se dois valores são diferentes. Para isso, usamos o operador `!=`.
```{r}
# Testes com resultado falso
1 != 1
"a" != "a"
# Testes com resultado verdadeiro
1 != 2
"a" != "b"
```
Para comparar se um valor é maior que outro, temos à disposição 4 operadores:
```{r}
# Maior
3 > 3
3 > 2
# Maior ou igual
3 >= 4
3 >= 3
# Menor
3 < 3
3 < 4
# Menor ou igual
3 <= 2
3 <= 3
```
Um outro operador muito útil é o `%in%`. Com ele, podemos verificar se um valor está dentro de um conjunto de valores (vetor).
```{r}
3 %in% c(1, 2, 3)
"a" %in% c("b", "c")
```
Nós começamos essa seção dizendo que usaremos testes lógicos o tempo todo. O motivo para isso é que eles fazem parte de uma operação muito comum na manipulação de bases de dados: os **filtros**.
No Excel, por exemplo, quando você filtra uma planilha, o que está sendo feito por trás é um teste lógico.
Falamos anteriormente que cada coluna das nossas bases de dados será representada dentro do R como um vetor. O comportamento que explica a importância dos testes lógicos na hora de filtrar uma base está ilustrado abaixo:
```{r}
minha_coluna <- c(1, 3, 0, 10, -1, 5, 20)
minha_coluna > 3
minha_coluna[minha_coluna > 3]
```
Muitas coisas aconteceram aqui, vamos por partes.
Primeiro, na operação `minha_coluna > 3` o R fez um excelente uso do comportamento de reciclagem. No fundo, o que ele fez foi transformar (reciclar) o valor `3` no vetor `c(3, 3, 3, 3, 3, 3, 3)` e testar se `c(1, 3, 0, 10, -1, 5, 20) > c(3, 3, 3, 3, 3, 3, 3)`.
Como os operadores lógicos também são vetorizados (fazem operações elemento a elemento), os testes realizados foram `1 > 3`, `3 > 3`, `0 > 3`, `10 > 3`, `-1 > 3`, `5 > 3` e, finalmente, `20 > 3`. Cada um desses testes tem o seu próprio resultado. Por isso a saída de `minha_coluna > 3` é um vetor de verdadeiros e falsos, respectivos a cada um desses 7 testes.
A segunda operação traz a grande novidade aqui: podemos usar os valores `TRUE` e `FALSE` para selecionar elementos de um vetor!
A regra é muito simples: **retornar** as posições que receberem `TRUE`, **não retornar** as posições que receberem `FALSE`. Portanto, a segunda operação é equivalente a:
```{r}
minha_coluna[c(FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, TRUE)]
```
O vetor lógico filtra o vetor `minha_coluna`, retornando apenas os valores maiores que 3, já que foi esse o teste lógico que fizemos.
Essa é a *mágica* que acontece por trás de filtros no R. Na prática, não precisaremos usar colchetes, não lembraremos da reciclagem e nem veremos a cara dos `TRUE` e `FALSE`. Mas conhecer esse processo é muito importante, principalmente para encontrar problemas de código ou de base.
Para finalizar, listamos na tabela abaixo os principais operadores lógicos.
```{r, echo=FALSE}
op_logico <- data.frame(
"Operador" = c("x < y", "x <= y", "x > y", "x >= y",
"x == y", "x != y", "!x", "x | y ",
"x & y", "x %in% y", "xor(x, y)"),
"Descrição" = c("x menor que y?", "x menor ou igual a y?",
"x maior que y?", "x maior ou igual a y?",
"x igual a y?", "x diferente de y?",
"Negativa de x", "x ou y são verdadeiros?",
"x e y são verdadeiros?",
"x pertence a y?",
"x ou y são verdadeiros (apenas um deles)?")
)
tabela(op_logico)
```
Por fim, veja algumas diferenças entre comparações lógicas no SQL e no R:
- **Igualdade**: no SQL é só um sinal de igual: `2 = 1`. No R são dois: `2 == 1`.
- **Diferença**: no SQL, usamos `<>`. No R usamos `!=`.
- **Negação**: em vez de usar a palavra `NOT` igual ao SQL, usamos `!` no R. Por exemplo, `id not in ('1', '2', '3')` fica `!(id %in% c(1, 2, 3))`.
### Exercícios {-}
**1** O código abaixo vai guardar no objeto `segredo` um número inteiro entre 0 e 10. Sem olhar qual número foi guardado no objeto, resolva os itens a seguir:
```{r, eval = FALSE}
segredo <- round(runif(1, min = 0, max = 10))
```
- **a.** Teste se o segredo é maior ou igual a 0.
- **b.** Teste se o segredo é menor ou igual a 10.
- **c.** Teste se o segredo é maior que 5.
- **d.** Teste se o segredo é par.
- **e.** Teste se `segredo * 5` é maior que a sua idade.
- **f.** Desafio. Escreva um teste para descobrir o valor do segredo.
**2.** Escreva um código em R que devolva apenas os valores maiores
ou iguais a 10 do vetor abaixo:
```{r, eval = FALSE}
vetor <- c(4, 8, 15, 16, 23, 42)
```
**3.** Use o vetor `numeros` abaixo para responder as questões seguintes.
```{r, eval = FALSE}
numeros <- -4:2
```
- **a.** Escreva um código que devolva apenas valores positivos do vetor `numeros`.
- **b.** Escreva um código que devolta apenas os valores pares do vetor `numeros`.
- **c.** Filtre o vetor para que retorne apenas aqueles valores que, quando elevados a 2, são menores do que 4.
## Valores especiais {#valoresEspeciais}
Vimos anteriormente que se você tentar acessar uma posição que não existe dentro de um vetor, ele retorna um valor estranho.
```{r}
vetor <- c(1, 2, 3)
vetor[4]
```
Esse valor, o `NA`, é tratado de forma especial no R. Ele representa a *ausência de informação*, isto é, a informação existe, mas nós (e o R) não sabemos qual é.
O `NA` para o R nada mais é do que o valor faltante ou omisso da Estatística. O famoso *missing*. Geralmente, quando temos uma base com valores faltando, como a idade para alguns indivíduos da nossa amostra, não significa que a idade deles não existe. Significa apenas que não temos essa informação.
Esse conceito é muito importante para entender o resultado da expressão abaixo.
```{r}
5 == NA
```
Em um primeiro momento, poderíamos esperar que o resultado fosse `FALSE`. Mas, sabendo o significado por trás do `NA` --- um valor desconhecido ---, a verdadeira pergunta que estamos fazendo é: 5 é igual a um valor que existe, mas que não sei qual é? É como se eu perguntasse se eu tenho 5 moedas na mão, mas lhe mostrasse a mão fechada. A resposta para isso é *não sei* ou, dentro do R, `NA`.
Um outro exemplo:
```{r}
idade_ana <- 30
idade_beto <- NA
idade_carla <- NA
idade_ana == idade_beto
idade_beto == idade_carla
```
Eu posso saber a idade da Ana, mas se eu não souber a idade do Beto, não sei se os dois tem a mesma idade. Por isso, `NA`. Da mesma forma, se não sei nem a idade do Beto nem da Carla, também não tenho como saber se os dois têm a mesma idade. Outra vez `NA`.
Mas e quando queremos saber se um valor é NA ou não? Para fazer esse teste, temos que rodar `is.na(valor-ou-objeto)`.
```{r}
is.na(NA)
is.na(idade_ana)
is.na(idade_beto)
```
Repare que essa função também é vetorizada.
```{r}
is.na(c(idade_ana, idade_beto, idade_carla))
```
Assim como o `NA`, existem outros valores especiais muito comuns no R.
O `NaN` (*not a number*) representa indefinições matemáticas.
```{r}
0/0
log(-1)
```
O `Inf` (infinito) representa um número muito grande (que o computador não consegue representar) ou um limite matemático.
```{r}
# O computador não consegue representar um número tão grande.
# O número é então """arredondado""" para infinito.
10^310
# Limite matemático.
1 / 0
# O "menos infinito" também existe.
-1 / 0
```
O `NULL` (nulo) representa a ausência de um objeto. Ele não tem significado prático para a análise dados. Está mais em sintonia com comportamentos de lógica de programação. Muitas vezes vamos definir um objeto como nulo para dizer ao R que não queremos dar um valor para ele. Muito utilizado em funções.
Da mesma forma que utilizados `is.na()` para testar se um objeto é `NA`, utilizamos `is.nan()`, `is.infinite()` ou `is.null()` para testar se um objeto é `NaN`, infinito ou nulo.
```{r}
nao_sou_um_numero <- NaN
objeto_infinito <- Inf
objeto_nulo <- NULL
is.nan(nao_sou_um_numero)
is.infinite(objeto_infinito)
is.null(objeto_nulo)
```
### Exercícios {-}
**1.** Quais as diferenças entre `NaN`, `NULL`, `NA` e `Inf`? Digite expressões que retornem cada um desses valores.
**2.** Escreva um código que conte o número de `NAs` do vetor `b`.
```{r, eval = FALSE}
b <- c(1, 0, NA, NA, NA, NA, 7, NA, NA, NA, NA, NA, 2, NA, NA, 10, 1, 1, NA)
```
## Listas
Chegamos ao último tópico antes de voltarmos aos data frames: as listas.
Listas são objetos muito importantes dentro do R. Primeiro porque **todo data frame é uma lista**. Segundo porque elas são bem parecidas com vetores, mas com uma diferença essencial: você pode misturar diferentes classes de objetos dentro dela.
Para criar uma lista, rodamos `list(valor1, valor2, valor3)`.
```{r}
list(1, "a", TRUE)
```
Veja que não houve coerção. Ainda temos um valor número, um texto e um valor lógico dentro da lista.
O *subsetting* de listas é um pouco diferente do que o de vetores. Isso porque **cada elemento de uma lista também é uma lista**. Veja o que acontece se tentarmos usar `[]` para pegar um elemento de uma lista.
```{r}
lista <- list(1, "a", TRUE)
lista[1]
class(lista[1])
```
O R nos retorna uma lista com apenas aquele elemento. Se quisermos o elemento de fato dentro de cada posição, precisamos usar dois colchetes:
```{r}
lista[[1]]
class(lista[[1]])
```
Cada elemento de uma lista ser uma lista é importante pois isso nos permite colocar vetores de tamanhos diferentes em cada posição. Isso faz das listas uma estrutura bem flexível para guardar dados.
```{r}
lista <- list(1:3, "a", c(TRUE, TRUE, FALSE, FALSE))
lista
lista[1]
lista[2]
lista[3]
```
É muito comum darmos nomes para cada posição de uma lista.
```{r}
dados_cliente <- list(cliente = "Ana Silva", idade = 25, estado_civil = NA)
dados_cliente
```
Agora, dentro da lista, o valor `Ana Silva`, por exemplo, está sendo atribuído ao nome `cliente`. Esse nome só existirá dentro da lista.
Um detalhe importante: os iguais utilizados nas atribuições dos nomes dentro da lista **não podem** ser substituídos por `<-`.
Quando as posições de uma lista tem nome, podemos acessar seus valores diretamente utilizando o operador `$`.
```{r}
dados_cliente$cliente
dados_cliente$idade
dados_cliente$estado_civil
```
Repare que o R devolve o valor dentro de cada posição, e não uma lista.
```{r}
dados_cliente[1]
dados_cliente$cliente
class(dados_cliente[1])
class(dados_cliente$cliente)
```
Isto implica que, nesse exemplo, `dados_cliente$cliente` é equivalente a `dados_cliente[[1]]`.
Conforme ficamos mais e mais proficientes na linguagem R, as listas passam a ficar cada vez mais frequentes. Voltaremos a falar delas diversas vezes nos próximos capítulos, em especial no Capítulo \@ref(funcionais).
## Mais sobre data frames
Chegou a hora de usarmos tudo o que aprendemos na seção anterior para exploramos ao máximo o nosso objeto favorito: o *data frame*.
Na seção anterior, nós dissemos que *data frames* são listas. Isso é importante pois todas as propriedades de uma lista valem para um *data frame*.
A melhor forma de entender essa equivalência é ver um *data frame* representado como uma lista.
```{r}
as.list(mtcars)
```
O código acima nos permite ver o *data frame* `mtcars` representado como uma lista. Veja que cada coluna da base se transforma em um elemento da lista. E o nome de cada coluna vira o nome de cada posição. Isso é interessante, pois podemos usar nos *data frames* as mesmas operações que aprendemos para listas.
Por exemplo, podemos usar o operador `$` para acessar cada elemento da lista, isto é, cada coluna do *data frame*.
```{r}
mtcars$mpg
```
E assim como cada elemento de uma lista também é uma lista, cada elemento (coluna) de um *data frame* também é um *data frame*.
```{r}
mtcars[1]
class(mtcars[1])
```
Mas se *data frames* são listas, por que existe a classe *data frame*? Na verdade, *data frames* são um tipo especial de listas, que têm as seguintes propriedades:
1. Todos os seus elementos (colunas) precisam ter o mesmo comprimento (número de linhas).
2. Todos os seus elementos (colunas) precisam ser nomeados.
3. *Data frames* têm 2 dimensões.
As propriedades (1) e (2) se devem ao formato das bases de dados. Elas são retangulares^[Também existem bases não retangulares, como dados de imagens por exemplos, mas não trataremos dessas estruturas neste livro.] --- observamos as mesmas variáveis (colunas) para todas as unidades amostrais (linhas)^[Mesmo quando uma variável não existe para uma unidade amostral, representamos esse valor como um *missing*] ---, e precisam ter algum nome especificando as colunas.
Da mesma forma que podemos ver um *data frame* como uma lista, também podemos fazer o inverso.
```{r}
dados_cliente <- list(
cliente = c("Ana Silva", "Beto Pereira", "Carla Souza"),
idade = c(25, 30, 23),
estado_civil = c(NA, "Solteiro", "Casada")
)
dados_cliente
as.data.frame(dados_cliente)
```
Quando tivermos valores faltantes na nossa base (células vazias no Excel), eles serão representados por `NA` nos *data frames*.
Observe que não conseguimos transformar uma lista em *data frame* se os elementos da lista não tiverem o mesmo comprimento.
```{r, error=TRUE}
dados_cliente <- list(
cliente = c("Ana Silva", "Beto Pereira", "Carla Souza"),
idade = c(25, 30),
estado_civil = c(NA, "Solteiro", "Casada")
)
as.data.frame(dados_cliente)