/
08-ggplot.Rmd
1302 lines (807 loc) · 97 KB
/
08-ggplot.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
# (PART) Visualizando seus dados {-}
# Visualização de dados com `ggplot2`
```{r, include=FALSE}
knitr::opts_chunk$set(echo = TRUE, out.width = "60%")
```
## Introdução e pré-requisitos
Esse é o primeiro capítulo em que vamos introduzir o pacote `ggplot2`, ou simplesmente `ggplot`. O `ggplot` é um pacote voltado para a visualização de dados, ou em outras palavras, para a construção de gráficos. Para que você possa acompanhar os exemplos dessa seção, você precisa ter o pacote instalado em sua máquina. Após instalá-lo, você pode tanto chamar diretamente pelo pacote `ggplot2`, quanto pelo `tidyverse`, que também o inclui, através da função `library()`.
```{r, eval = FALSE}
library(ggplot2)
library(tidyverse)
```
## O que é o `ggplot` e a sua gramática
A linguagem R é conhecida por sua capacidade gráfica, e @murrell2006 oferece ótimos exemplos que atestam essa afirmação. Mesmo que a linguagem R ofereça "já de fábrica", o pacote `lattice`, que já é capaz de muita coisa, o `ggplot` é sem dúvidas, o pacote mais popular da linguagem no que tange a criação de gráficos, pois ele oferece algo que os outros pacotes não tem, que é a sua *flexibilidade*^[Ou seja, em relação a seus concorrentes, o `ggplot` não é necessariamente o pacote que oferece praticidade, mas sim, um leque de possibilidades muito maior em relação a seus concorrentes.].
```{r,fig.align='center',fig.cap= 'phases9032 por Thomas Lin Pedersen' ,out.width='70%', echo=FALSE}
knitr::include_graphics('Figuras/phases9032.png')
```
Flexibilidade é uma das principais características (e a principal vantagem) do `ggplot`, e é o que amplia a sua utilização para além dos gráficos sérios e frios de um jornal científico, permitindo ao usuário criar gráficos vistosos, e um tanto peculiares. Veja por exemplo, a arte criada por Thomas Lin Pedersen, mostrada na figura 8.1. O que lhe dá essa liberdade dentro do `ggplot`, é a sua gramática.
O pacote `ggplot` (ou seu nome oficial - `ggplot2`) foi inicialmente desenvolvido por @wickham2016, e lançado pela primeira vez no ano de 2005. O pacote representa uma implementação da teoria desenvolvida por @wilkinson, chamada de *The Grammar of Graphics* (ou "a gramática dos gráficos"). Portanto, o `ggplot` busca abstrair os principais conceitos da teoria de @wilkinson, e implementá-los dentro da linguagem R.
Segundo a teoria de @wilkinson, todo e qualquer gráfico estatístico, pode ser descrito por um conjunto de camadas, ou componentes, que estão apresentados na figura 8.2. Dessa forma, na visão de @wilkinson todos os tipos de gráfico que conhecemos (pizza, barras, dispersão, *boxplot*, etc.) fazem parte de um mesmo grupo, e a característica que os tornam diferentes entre si, se encontra na forma como as camadas abaixo estão definidas em cada gráfico.
```{r, echo = FALSE, fig.cap = "Camadas de um gráfico do ggplot, baseado em Wickham (2016)"}
knitr::include_graphics("Figuras/camadas_grafico.png")
```
Tendo isso em mente, um gráfico do `ggplot` é composto por várias camadas, que em conjunto formam o gráfico desejado. A ideia por trás do pacote, portanto, é utilizar uma gramática para descrever de forma concisa, cada uma das camadas apresentadas na figura 8.2. Após definirmos essas camadas, nós podemos somá-las para construirmos o nosso gráfico final. Em outras palavras, você vai adicionando aos poucos, novas camadas ao gráfico, onde cada uma dessas camadas fica responsável por definir um componente específico do gráfico (escalas, formas geométricas, legendas, facetas, anotações, ...). Caso seja de seu desejo, você pode deixar o próprio `ggplot` responsável por definir várias das camadas apresentadas na figura 8.2. Porém, em todo gráfico do `ggplot`, você deve obrigatoriamente definir as três camadas (em negrito na figura 8.2) apresentadas a seguir, sendo portanto, as camadas **essenciais** que formam a base de todo gráfico do `ggplot`.
1. Dados: os dados que o gráfico deve expor.
2. Mapeamento estético (*aesthetic mapping*): uma descrição de como as variáveis dispostas em seus dados devem ser mapeadas para elementos visuais (ou estéticos) de seu gráfico.
3. Geometrias: são as formas geométricas do gráfico que representam os seus dados, ou seja, em um gráfico de dispersão, seus dados são representados no gráfico por *pontos*, enquanto em um gráfico de barras, seus dados são representados por *retângulos*.
A gramática do `ggplot`, representa, portanto, as regras que definem o emprego das funções necessárias, e de seus possíveis parâmetros para acessarmos e controlarmos cada uma das camadas mostradas na figura 8.2. Logo, cada uma dessas camadas, são controladas por uma função (ou por um conjunto de funções) diferente, que lhe permite o uso de diferentes mecanismos e valores em sua definição.
## Iniciando um gráfico do `ggplot`
### Dados
Primeiro, vamos definir os dados que vamos utilizar em nossos gráficos. A tabela `datasus`, contém a contagem de mortes por homicídios dolosos em 2018 no Brasil, coletados a partir dos microdados do SIM/DATASUS. Nessa mesma tabela, temos a distribuição dessas mortes, por sexo, por faixa etária, pelo estado (Unidade da Federação - UF) em que as mortes ocorreram, e pela cor de pele dos indivíduos.
```{r, include = FALSE}
library(readr)
github <- "https://raw.githubusercontent.com/pedropark99/"
pasta <- "Curso-R/master/Dados/"
arquivo <- "datasus.csv"
datasus <- read_csv2(paste0(github, pasta, arquivo))
```
```{r, eval = FALSE}
library(readr)
github <- "https://raw.githubusercontent.com/pedropark99/"
pasta <- "Curso-R/master/Dados/"
arquivo <- "datasus.csv"
datasus <- read_csv2(paste0(github, pasta, arquivo))
```
```
## Rows: 1836 Columns: 6
## -- Column specification -----------------------------------
## Delimiter: ";"
## chr (5): Faixa etaria, Genero, Cor, Nome UF, UF
## dbl (1): Contagem
##
## i Use `spec()` to retrieve the full column specification for this data.
## i Specify the column types or set `show_col_types = FALSE` to quiet
## this message.
```
```{r}
datasus
```
Vamos começar a montar o nosso gráfico. Você **sempre** inicia um gráfico de `ggplot`, pela função base do pacote - `ggplot()`. Essa função é responsável por criar o objeto base para o gráfico, e nela, possuímos dois argumentos que compõe duas das três camadas essenciais (que definimos na seção 8.2) desse gráfico, e que podem ou não ser fornecidos nessa função. Esses dois argumentos são: *data*, que é o nome da tabela onde estão os dados que serão utilizados no gráfico; e *mapping*, que é o *aesthetic mapping*, ou o mapeamento de variáveis de sua tabela, para componentes estéticos do gráfico. Ou seja, você não precisa necessariamente fornecer esses argumentos já na função `ggplot()`, pois você pode defini-los dentro das funções que formam as figuras geométricas (as funções `geom`). O importante, é que você sempre deve começar um gráfico `ggplot`, com a função `ggplot()`.
Mas então, qual é a diferença entre eu fornecer esses argumentos na função `ggplot()` ou dentro das funções `geom`? Pense em um exemplo, no qual você busca mostrar em um mesmo gráfico, duas informações diferentes. Você pode utilizar dois `geom`'s (ou formas geométricas) diferentes para mostrar e diferenciar essas duas informações no gráfico. Por exemplo, podemos ter um gráfico que contenha barras mostrando a evolução da dívida pública, e linhas mostrando a evolução do salário médio no país.
Caso você forneça os dois argumentos (*data* e *mapping*) na função `ggplot()`, você está dizendo ao programa, que ele deve utilizar a mesma base de dados, e o mesmo *aesthetic mapping*, em todos os formatos geométricos (`geom`) do gráfico. Enquanto, ao fornecer esses argumentos dentro de cada função `geom`, você estaria dizendo ao programa que utilize essa base de dados, e esse *aesthetic mapping*, apenas naquele formato geométrico (ou `geom`) especificamente. Tendo isso em mente, não conseguiríamos montar o gráfico descrito no parágrafo anterior, ao dar os argumentos já na função `ggplot()`. Pois o gráfico mostra duas informações diferentes (salário médio e dívida pública), ao longo dos `geom`'s do gráfico. Ou seja, os dois formatos geométricos dispostos no gráfico, utilizam dois *aesthetic mapping* diferentes. Quando chegarmos à seção 8.4 vou explicar isso em mais detalhes.
No nosso caso, os dados que vamos utilizar, estão na tabela `datasus`, por isso forneço ao argumento *data* o nome dessa tabela. Ao rodar o código logo abaixo, você vai perceber que ele gera apenas um quadro cinza vazio. Isso ocorre porque definimos apenas uma das camadas essenciais para compor o gráfico, que são os dados utilizados. Temos que definir as outras duas, para completarmos a base de um gráfico, por isso, vamos passar agora para o *aesthetic mapping*.
```{r,eval = FALSE}
ggplot(data = datasus)
```
### Mapeamento de variáveis (*Aesthetic Mapping*)
O *aesthetic mapping* representa o mapeamento, ou a conexão de variáveis em sua tabela (ou sua base de dados), com os componentes estéticos e visuais do gráfico. Nós controlamos esse mapeamento através da função `aes()`. Há diversos desses componentes visuais que compõe um gráfico, e os primeiros que vêm a sua mente, são provavelmente as cores e as formas geométricas. Mas também os próprios eixos, ou melhor dizendo, as escalas utilizadas nos eixos, são componentes visuais do gráfico. Pois essas escalas definem como as formas geométricas vão se posicionar dentro do espaço do gráfico.
Pense por exemplo, no globo terrestre. Você pode representar esse globo dentro do `ggplot`, mas para que os formatos sejam corretamente posicionados em um "globo", você precisa usar uma escala e um sistema de coordenadas diferentes do plano cartesiano. Um outro exemplo, seria o gráfico de pizza. Ao pesquisar sobre, você irá perceber que um gráfico de pizza no `ggplot`, é feito a partir do formato geométrico de barras (`geom_bar()`). Ou seja, um gráfico de barras, é o ponto de partida para gerar um gráfico de pizza no `ggplot`, e o que diferencia esses dois gráficos, é a escala usada. Em um gráfico de pizza, utilizamos uma coordenada circular, chamada de coordenada polar, ao invés do plano cartesiano.
Agora, vamos continuar montando nosso gráfico. Primeiro, vamos tentar montar um gráfico de barras, que mostre a distribuição do total de mortes ao longo das faixas etárias no país, baseado nos dados apresentados na tabela `datasus`. Tendo isso em mente, o número de mortes, deve ficar no eixo y de nosso gráfico, enquanto os grupos (faixas etárias), devem ficar no eixo x.
Essa é a base do nosso mapeamento de variáveis. Estamos definindo que o número de mortes deve ficar no eixo y, e as faixas etárias no eixo x, e nós concedemos essa descrição ao `ggplot`, dentro da função `aes()` (abreviação para *aesthetic mapping*). Dessa vez, ao rodar o código abaixo você vai perceber que um plano cartesiano foi montado, onde temos uma escala para a faixa etária no eixo x, e outra escala para o total de mortes no eixo y. Porém, esse plano cartesiano continua vazio, pois ainda não definimos a última camada essencial do gráfico, que é a forma geométrica que deve representar os nossos dados.
```{r}
ggplot(
data = datasus,
mapping = aes(x = `Faixa etaria`, y = Contagem)
)
```
Portanto, vamos adicionar ao nosso código, nossa primeira função `geom`. Cada função `geom`, se refere a um formato geométrico diferente. No nosso caso, queremos um gráfico de barras, que é formado pela função `geom_bar()`. O padrão dessa função (ou formato geométrico) no `ggplot`, é calcular uma contagem dos dados. Em outras palavras, o gráfico de barras no `ggplot`, se comporta inicialmente (por padrão) como um histograma. Ao invés de calcular a soma total de certa variável, ele irá contar, quantas vezes cada valor ocorre naquela variável dentro da base de dados.
Entretanto, não queremos uma contagem dos dados, pois a coluna `Contagem` já representa uma contagem em si. O que queremos é a soma total dessa contagem em cada faixa etária. Por isso, ao invés de fornecer `Contagem` ao argumento *y*, eu defino essa coluna para o argumento *weight*. Todas as funções que adicionarmos às várias camadas do nosso gráfico, devem ser conectadas por um sinal de `+`, por isso lembre-se de colocar esse sinal sempre que adicionar uma nova função ao seu gráfico.
```{r}
ggplot(
data = datasus,
mapping = aes(x = `Faixa etaria`, weight = Contagem)
) +
geom_bar()
```
Agora que definimos as três camadas essenciais (dados, *aesthethic mapping* e `geom`), temos enfim o nosso primeiro gráfico montado. Há várias coisas que poderíamos fazer a partir daqui. Podemos por exemplo, colorir as barras de acordo com a participação do sexo no número de mortes. Ou seja, essas cores irão representar em cada barra, o número de mortes que correspondem ao sexo masculino e ao sexo feminino. Por padrão, o `geom_bar()` empilha esses agrupamentos um em cima do outro. Dessa forma, essas cores não apenas nos apresenta o número de mortes em cada sexo, mas indiretamente, elas também nos mostram o quanto que aquele grupo representa (qual a sua porcentagem) do total de mortes naquela faixa etária.
Desta maneira, estamos definindo um outro componente visual do gráfico (cores das barras) à uma outra variável de nossos dados (coluna `Genero`). Logo, estamos falando novamente do *aesthethic mapping* do gráfico, e por isso, devemos definir essa ligação dentro da função `aes()`. Há duas formas de você colorir formas geométricas no `ggplot`, que dependem da forma geométrica e do resultado que você quer atingir. Uma barra (ou retângulo), é tratada como uma forma geométrica de área, enquanto outras formas (como pontos e linhas) são tratadas de uma maneira diferente. Nesses formatos de área, você deve utilizar o argumento `fill`, para preencher o interior deste formato de uma cor.
```{r}
ggplot(
data = datasus,
mapping = aes(
x = `Faixa etaria`,
weight = Contagem,
fill = Genero
)
) +
geom_bar()
```
Conseguimos colorir as barras, e podemos ver que uma parte muito pequena das mortes correspondem ao sexo feminino, em todas as faixas etárias. Agora, e se mudássemos a variável de grupos (faixas etárias) do nosso gráfico? Vamos conectar uma variável diferente ao eixo x, por exemplo, a cor de pele. Perceba, que o restante do *aesthetic mapping* continua o mesmo, e portanto, o gráfico mantém essas outras "conexões" enquanto modifica a variável ligada ao eixo x.
```{r}
ggplot(
data = datasus,
mapping = aes(
x = Cor,
weight = Contagem,
fill = Genero
)
) +
geom_bar()
```
Como disse anteriormente, há outros componentes visuais que você pode ligar às variáveis de sua tabela de dados. Você pode por exemplo, em alguns `geom`'s, conectar o *formato* desse `geom` a uma variável. Eu sei, sua cabeça provavelmente deu uma volta com esse exemplo: "Como assim? Eu posso variar o formato de uma forma geométrica ao longo do gráfico?". Na seção 8.4 dou um exemplo dessa estratégia.
### Formatos geométricos - funções `geom`
Cada função `geom` utiliza um formato geométrico e uma forma de desenho diferentes, para desenhar e representar os seus dados. No `ggplot` há vários `geom`'s distintos que você pode utilizar. Abaixo estou listando os `geom`'s mais comuns, mas basta consultar o painel de dicas do RStudio^[https://rstudio.com/wp-content/uploads/2015/03/ggplot2-cheatsheet.pdf], ou o site oficial de referências do pacote^[https://ggplot2.tidyverse.org/reference/index.html], que você ficará um pouco perdido com tantas opções. Um excelente repositório, com ótimos exemplos de gráficos dos quais você pode tirar inspirações de como e onde utilizar cada `geom`, é o *R Graph Gallery*^[https://www.r-graph-gallery.com/].
1. `geom_bar()`: desenha um gráfico de barras.
2. `geom_point()`: desenha um gráfico de pontos (ou um gráfico de dispersão).
3. `geom_line()`: desenha um gráfico de linha.
4. `geom_boxplot()`: desenha um gráfico de *boxplot*.
5. `geom_histogram()`: desenha um histograma.
6. `geom_sf()`: desenha um mapa (`geom` para dados espaciais).
7. `geom_smooth()`: desenha uma linha de média condicional (muito utilizado para desenhar linhas que representam modelos de regressão linear e de outros modelos econométricos).
8. `geom_text()`: utilizado para inserir texto.
9. `geom_label()`: utilizado para inserir rótulos, ou basicamente, textos envoltos por uma caixa.
Por exemplo, um gráfico de barras, é geralmente utilizado para apresentar estatísticas descritivas dos nossos dados. Ou seja, esse tipo de gráfico (por padrão) tenta resumir características dos seus dados em poucos números (médias, totais, contagens). Já um gráfico de dispersão (por padrão) nos apresenta diretamente os dados, de forma crua no plano cartesiano. Isto é, diferentes `geom`'s vão tratar (e principalmente, representar) os seus dados de formas distintas. Vamos por exemplo, adicionar pontos ao nosso gráfico anterior, com o `geom_point()`.
Para facilitar a visualização, eu limitei os valores do eixo y no gráfico (para o intervalo de 0 a 1500) por meio da função `lims()`. Dessa forma, estamos dando um *zoom* em uma área específica do gráfico. Repare que cada ponto representa uma das observações encontradas na nossa base, e que vários deles estão se sobrepondo.
```{r}
ggplot(
data = datasus,
mapping = aes(
x = Cor,
weight = Contagem,
fill = Genero
)
) +
geom_bar() +
geom_point(aes(y = Contagem)) +
lims(y = c(0,1500))
```
Ao substituirmos as barras por *boxplot*'s produzimos um gráfico que além de mostrar todas observações da base com o `geom_point()`, ele também mostra como a distribuição de ambos os sexos se encaixam ao longo do alcance (ou *range*) desses dados. Podemos perceber que nos indivíduos de cor parda, a maior contagem para o sexo feminino em toda a base, atinge em torno de 175 mortes, enquanto para o sexo masculino, esses valores podem atingir mais de 1000 mortes, apesar de que ambos os valores são *outliers* em suas respectivas distribuições.
```{r}
ggplot(
data = datasus,
mapping = aes(
x = Cor,
y = Contagem,
fill = Genero
)
) +
geom_boxplot() +
geom_point()
```
Uma outra forma de visualizarmos a diferença entre homens e mulheres nesses dados, seria utilizando `geom`'s de erro, como as linhas de alcance. Os `geom`'s de erro são muito úteis para visualizar medidas de variação ao longo dos grupos. O `geom_ribbon()` por exemplo, é utilizado em gráficos de séries temporais, para desenhar os intervalos de confiança ou desvios padrão ao redor da linha que representa a série. No nosso caso, iremos utilizar o `geom_linerange()`, para desenharmos a diferença média entre o número de mortes entre os dois gêneros.
O que o `geom_linerange()` faz é desenhar uma reta de um ponto A a um ponto B. A ideia por traz desse `geom` é desenharmos um linha que representa (pelo seu comprimento), por exemplo, o desvio padrão de uma variável, ou no nosso caso, a diferença na média de vítimas de homicídios dolosos entre dois gêneros. Isto significa que temos dois novos componentes visuais que podemos controlar no gráfico através do *aesthetic mapping*, que são as coordenadas do ponto A e do ponto B. Esses componentes (pontos A e B) representam os "limites" (máximo e mínimo) dessa linha, por isso, são controlados pelos argumentos `ymax` e `ymin` dentro da função `aes()`. Há outros `geom`'s que podem ser controlados por esses argumentos, porém, os que vimos anteriormente (`geom_point()` e `geom_bar()`) não possuem esses argumentos.
Primeiro, precisamos calcular o número médio de mortes de cada gênero e em cada cor de pele, e em seguida, modificar a estrutura da tabela, para que possamos mapear os limites (`ymin` e `ymax`) do *linerange* de acordo com o sexo. Para isso utilizo funções do pacote `dplyr`, portanto lembre-se de chamar por esse pacote com `library()`, para ter acesso a essas funções. Perceba também que eu inverti o plano cartesiano, utilizando a função `coord_flip()`.
```{r, message=FALSE}
datasus_agrup <- datasus %>%
group_by(Cor, Genero) %>%
summarise(Media = mean(Contagem)) %>%
pivot_wider(
id_cols = "Cor",
names_from = "Genero",
values_from = "Media"
)
ggplot(
data = datasus_agrup,
aes(x = Cor)
) +
geom_linerange(aes(ymax = Masculino, ymin = Feminino)) +
geom_point(aes(y = Feminino, color = "Feminino")) +
geom_point(aes(y = Masculino, color = "Masculino")) +
coord_flip()
```
Agora, muitas coisas estão ocorrendo neste gráfico. Primeiro, o `geom_linerange()` constrói uma linha para cada cor de pele, que vai da média de mortes no sexo feminino até a média no sexo masculino. Segundo, dois `geom_point()` são utilizados, onde cada um deles fica responsável por um dos sexos, e desenha um único ponto para cada cor de pele que indica a média de mortes para o sexo correspondente. Em seguida, eu uso `coord_flip()` para inverter o plano cartesiano. Ou seja, a variável que estava no eixo y (média de mortes) vai para o eixo x, e a variável que estava no eixo x (cor de pele) vai para o eixo y.
Certamente, esse gráfico dá um pouco mais de trabalho de construir. Porém, é uma forma mais simples de se mostrar essa diferença, e com isso, você consegue atingir um público maior. Pode ser que o seu leitor não saiba o que é um *boxplot*, e há razões razoáveis para se acreditar nisso. No Brasil, o *boxplot* não é comumente tratado no ensino básico, e sim no ensino superior, e mais especificamente, em cursos que sejam da área de exatas, ou que possuam matérias de estatística na grade curricular. Nós sabemos também que o acesso da população brasileira ao ensino superior é restrito, sendo considerado um local de "elitismo".
Por outro lado, os alunos em geral veem as principais medidas estatísticas de posição central (média, mediana e moda) já no ensino básico, e alguns chegam a revê-las no ensino superior. Logo, as chances de seu leitor compreender a mensagem que você quer passar: "em média, os homens são as principais vítimas de homicídios dolosos, entretanto, nas populações indígenas e de cor de pele amarela, esse padrão não parece ser significativo" são maiores. Essa consideração pode ter menor peso a depender de qual seja o público que você busca atingir. Se você está publicando um artigo científico em sua área, é bem provável que os potenciais leitores deste material conheçam um *boxplot*, e portanto, saibam interpretá-lo corretamente.
## Uma outra forma de se compreender o *aesthetic mapping*
Nas seções anteriores, eu defini o *aesthetic mapping*, como a conexão entre as variáveis de sua tabela, com os componentes visuais de seu gráfico. Porém, temos uma outra forma útil de enxergarmos esse sistema. Podemos entender o *aesthetic mapping*, como um mecanismo para determinarmos quais componentes visuais vão variar, e quais vão permanecer constantes ao longo do gráfico. Ou seja, se você está definindo, por exemplo, as cores da forma geométrica (`geom`) que representa os seus dados, você pode utilizar o *aesthetic mapping* para definir se e como essas cores vão variar ao longo do gráfico.
Por exemplo, vamos voltar ao gráfico de barras que montamos na seção 8.3, que mostra o número total de mortes ao longo das diferentes cores de pele e gênero da base. Perceba, que a cor está variando dentro de cada barra (e não entre cada uma delas), de acordo com a variável `Genero`.
```{r}
datasus %>%
ggplot() +
geom_bar(
aes(x = Cor, weight = Contagem, fill = Genero)
)
```
Nós podemos modificar a forma como essas cores variam dentro de cada barra, ao mudarmos a variável que define essa variação. Em outras palavras, podemos alterar o comportamento das cores, ao conectar esse componente em `aes()`, a uma outra variável de nossa tabela. Como exemplo, podemos atribuir às UF's da base. Perceba que temos agora, uma variação muito maior de cores dentro de cada barra.
```{r}
datasus %>%
ggplot() +
geom_bar(
aes(x = Cor, weight = Contagem, fill = UF)
)
```
Nós podemos ainda, atribuir a mesma variável alocada no eixo x para definir a variação dessas cores ao longo do gráfico. Dessa forma, temos um gráfico onde cada uma das barras terá a sua própria cor. Isso não é particularmente útil, mas talvez você deseja ter uma cor separada para cada barra, e caso você esteja com preguiça de pensar e definir quais cores serão essas, deixar essa tarefa nas mãos do próprio `ggplot` é uma solução e um atalho simples para atingir um bom resultado.
```{r}
datasus %>%
ggplot() +
geom_bar(
aes(x = Cor, weight = Contagem, fill = Cor)
)
```
Portanto, ao conectarmos diferentes variáveis com o argumento (`fill`) em `aes()`, que define como as cores de cada barra são compostas, podemos modificar a forma como essas cores variam ao longo do gráfico. Mas e se nós quisermos manter uma única cor para essas barras, ou seja, e se é de seu desejo manter as cores constantes ao longo de todo o gráfico? Para isso, basta que você defina essas cores, fora de `aes()`.
Em outras palavras, a função `aes()` trabalha com **variáveis**, ou atributos de suas observações que tendem a variar ao longo de sua base. Quando você estiver trabalhando com valores constantes, ou com atributos que possuem um único valor possível ao longo de toda a sua base, a função `aes()` provavelmente não será o lugar ideal para trabalharmos com tais valores.
Por exemplo, o R possui diversas cores pré-programadas em seu sistema, e sempre que você quiser acessar essas cores ao longo do `ggplot`, você pode se referir a elas, através de seus nomes registrados. Caso queira uma lista com os nomes dessas cores pré-programadas, você pode utilizar a função `colors()`. Dentre essas diversas cores, temos uma chamada de `steelblue`. Logo, caso eu queira que todas as barras do meu gráfico estejam coloridas de acordo com essa cor, eu preciso fornecer o nome dessa cor ao argumento `fill`, de fora da função `aes()`.
```{r}
datasus %>%
ggplot() +
geom_bar(
aes(x = Cor, weight = Contagem),
fill = "steelblue"
)
```
Portanto, você pode aplicar essa metodologia para qualquer outro componente visual de seu gráfico que pode ser definido. Ou seja, se você deseja manter algum dos componentes visuais, definidos por um dos argumentos de `aes()` (`fill`, `color`, `size`, `fontface`, `linetype`, `shape`, etc.), constantes, você precisa apenas definir esses argumentos fora de `aes()`. Por outro lado, caso você queira controlar a forma como algum desses componentes visuais variam ao longo do gráfico, você precisa definir esses argumentos dentro de `aes()`.
Porém, você talvez se pergunte: o que ocorre se eu fornecer a cor `steelblue` dentro de `aes()`? Será que o `ggplot` reconhece que queremos aplicar essa cor sobre as formas geométricas do gráfico? A resposta curta é não, mas o resultado em geral é um pouco estranho, ou no mínimo algo inesperado. Pois em um caso como esse, a função `aes()` irá entender que você deseja colorir as barras no gráfico, de acordo com uma nova variável em sua tabela, chamada `fill`, e que possui um único valor possível ao longo da base, mais especificamente, o texto `steelblue`.
Esse comportamento ocorre sempre que você fornece um valor em texto (um *string*) à algum argumento de `aes()`. Em uma situação como essa, o `ggplot()` parece criar uma nova variável em sua tabela chamada `fill`, e que contém o valor em texto que você forneceu a esse argumento. Isso não necessariamente é um comportamento inadequado, mas ele certamente surpreende alguns usuários, e como ele tem se mantido ao longo das últimas versões do `ggplot`, é possível que ele continue a funcionar dessa forma, por um bom tempo.
```{r}
datasus %>%
ggplot() +
geom_bar(
aes(x = Cor, weight = Contagem, fill = "steelblue")
)
```
## Sobrepondo o *aesthetic mapping* inicial em diversas camadas
Agora, vou explicar em maiores detalhes qual é a diferença entre: preenchermos os argumentos de `data` e `mapping` já na função inicial do gráfico (`ggplot()`), e de preenchê-los nas funções `geom`.
Para isso, vamos usar outros dados. Na tabela PIB eu possuo uma série histórica mensal do índice de faturamento real da indústria (`Faturamento_indus`), da porcentagem do PIB que representa a dívida pública líquida (`Divida_liq_perc`), e a média mensal da taxa de investimento produtivo (taxa de formação bruta de capital fixo - `FBCF`) na economia brasileira, além de dados de PIB, coletados do IPEAData^[http://www.ipeadata.gov.br/Default.aspx].
```{r, include = FALSE}
PIB <- read_csv2('Dados/Serie_PIB.csv')
PIB$Data <- parse_date(PIB$Data, format = "%d/%m/%Y")
```
```{r}
PIB
```
Na seção 8.3, expliquei que ao preencher os argumentos já no `ggplot()` você estaria pedindo ao programa, que utilize a mesma base de dados e/ou o mesmo *aesthetic mapping* ao longo de todas as camadas do gráfico. Como exemplo, veja o que acontece no gráfico abaixo.
Como o `geom_bar()` busca resumir os nossos dados em poucas estatísticas, eu coloquei dessa vez o valor *"identity"* no argumento `stat`. Isso impede que ele agrupe os dados em alguma medida estatística, fazendo com que o `geom` apenas identifique os valores que aparecem na base, da mesma forma que um `geom_point()` faria. Perceba também, que eu estou utilizando três `geom`'s diferentes no gráfico. Mas como eu não defini um *aesthetic mapping* específico em cada um deles, todos esses `geom`'s estão mostrando exatamente a mesma informação. Dito de outra forma, estes `geom`'s estão utilizando o mesmo *aesthetic mapping*, o qual definimos na função `ggplot()`.
```{r}
ggplot(
data = PIB,
aes(x = Data, y = Faturamento_indus)
) +
geom_bar(stat = "identity", fill = "darkgray") +
geom_line(color = "blue") +
geom_point(color = "red")
```
Você deve estar pensando: "Ok, mas isso não faz sentido! Por que eu usaria três `geom`'s diferentes para uma mesma informação?". Bem, pode ser que você queira utilizar mais de um `geom` que mostre a mesma informação, por questões estéticas no gráfico. Um exemplo simples, seria marcar a borda de uma linha criada por `geom_line()`. Ou seja, não há uma forma direta e simples em `geom_line()` (algo que já é possível de ser feito no `geom_point()`), de pintar essas bordas de uma cor mais escura (ou clara) do que o interior da linha, dando assim uma maior ênfase para aquela linha. Portanto, a ideia seria criarmos duas camadas de `geom_line()`: uma interna, com uma linha mais estreita e de cor mais clara (ou mais escura); e uma externa, com uma linha mais larga (de forma que ela "transborde" para fora da linha interna) e de cor mais escura (ou mais clara).
De qualquer maneira, esses `geom`'s não fazem muito sentido da forma como estão dispostos no momento, portanto, vamos mudar de estratégia. Por que não utilizamos um só `geom` para apresentar três informações diferentes?! Para isso, temos que modificar a nossa base levemente. O objetivo é pegar as três colunas com as variáveis que vamos plotar (`Faturamento_indus`, `FBCF` e `Divida_liq_perc`), e agrupá-las em duas colunas: uma com os valores dessas variáveis, e outra coluna com os nomes dessas variáveis, para identificar qual variável o valor na primeira coluna se refere. Realizamos esse trabalho pela função `pivot_longer()`.
```{r}
PIB_remodelado <- PIB %>%
select(Data, Faturamento_indus, FBCF, Divida_liq_perc) %>%
pivot_longer(
cols = c("Faturamento_indus", "FBCF", "Divida_liq_perc"),
names_to = "Nome_variavel",
values_to = "Valor"
)
ggplot(
data = PIB_remodelado,
aes(x = Data, y = Valor, linetype = Nome_variavel)
) +
geom_line()
```
Novamente, como não incluímos uma função `aes()`, ou definimos o argumento `data` dentro do `geom_line()`, ele irá utilizar o `data` e o *aesthetic mapping* (`aes()`) que definimos em `ggplot()`. Lembra de quando eu disse que você poderia controlar o formato de um `geom` de acordo com uma variável? O gráfico acima é um exemplo prático disso. Estamos utilizando apenas um `geom` para mostrar três informações diferentes, e o componente estético que utilizamos para diferenciar essas informações no gráfico, é o formato dessas linhas. Portanto, ao definirmos o componente `linetype` para *Nome_variavel*, estamos modificando o formato da linha (tracejada ou sólida), de acordo com os valores dessa variável. Poderíamos usar a mesma estratégia em `geom_point()`, ao definirmos o argumento `shape` para *Nome_variavel*. O resultado, seria um gráfico com pontos de três formatos diferentes (triângulos, quadrados e pontos comuns).
Entretanto, para utilizarmos essa estratégia, nós tivemos que reestruturar a nossa base de dados pela função `pivot_longer()`. E se você não quisesse modificar essa base? Infelizmente, sem essa modificação, não poderíamos mostrar as três variáveis utilizando apenas uma função `geom`, mas poderíamos realizar o mesmo trabalho com uma função `geom` para cada variável. Neste caso, teremos que utilizar um *aesthetic mapping* diferente para cada `geom`, pois cada um deles, ficará responsável por mostrar os valores de uma variável diferente.
No primeiro gráfico dessa seção, utilizamos três `geom`'s diferentes para mostrar uma mesma informação. Se você comparar o código desse primeiro gráfico, ao código do gráfico abaixo, você perceberá que eles são quase idênticos, o que mudou, é a presença da função `aes()` nos dois últimos `geom`'s.
```{r}
ggplot(
data = PIB,
aes(x = Data, y = Faturamento_indus)
) +
geom_bar(stat = "identity", fill = "darkgray") +
geom_line(aes(y = FBCF), color = "blue") +
geom_line(aes(y = Divida_liq_perc), color = "red")
```
O único `geom` que não possui uma função `aes()` definida, é o `geom_bar()`, logo, esse `geom` vai seguir o *aesthetic mapping* que definimos em `ggplot()`. Já os outros dois `geom`'s, vão seguir o *aesthetic mapping* que definimos em seus respectivos `aes()`. Porém, repare que em ambos `geom`'s, eu apenas defini a variável mapeada para o eixo y, não cheguei a definir uma nova variável para o eixo x. Quando isso ocorre, a função irá novamente recorrer ao *aesthetic mapping* que você definiu em `ggplot()`. Ou seja, como não definimos uma nova variável para o eixo x, todos os `geom`'s do gráfico acabam utilizando a variável no eixo x definida em `ggplot()`.
Portanto, você pode sobrepor por completo, ou parcialmente, o *aesthetic mapping* definido em `ggplot()` em cada `geom`, basta omitir os termos dos quais você não deseja sobrepor na nova função `aes()`. Um outro detalhe, é que não chegamos a definir em nenhum momento, um novo valor para o argumento *data* em algum `geom`. Logo, apesar de estarmos utilizando diferentes *aesthetic mappings*, todos os `geom`'s estão utilizando a mesma base de dados.
### Resumo da estrutura básica de um gráfico `ggplot()`
Em resumo, todo gráfico do `ggplot()` possui três camadas essenciais, que formam a base do gráfico: 1) *data*, a base (ou bases) de dados utilizada no gráfico em questão; 2) *aesthetic mapping*, o mapeamento, ou a ligação de variáveis presentes na base de dados, para componentes estéticos e visuais do gráfico; 3) *geom*, a forma geométrica (retângulos, pontos, polígonos, linhas, etc) que irá representar os seus dados no gráfico.
Para construir um gráfico do `ggplot()`, você deve sempre definir esses componentes. Os dois primeiros (*data* e *aesthetic mapping*), podem ser definidas dentro da função `ggplot()`, já o terceiro (*geom*), você define ao utilizar uma (ou várias) das funções `geom`, em uma (ou em várias) das camadas do gráfico. Com isso, temos uma estrutura básica como a definida abaixo, para construirmos um gráfico do `ggplot`:
```{r,eval=FALSE}
ggplot(
data = <sua base de dados>,
aes(<aesthetic mapping>)
) +
<geom_...> #uma função geom a seu gosto
```
Lembre-se que essa é apenas uma estrutura básica. Como mostramos na seção 8.4, podemos sobrepor de diversas formas essa estrutura. E podemos definir diversos outros parâmetros sobre essa estrutura como foi mostrado ao longo do capítulo.
## Uma discussão sobre os principais `geom`'s
Nas próximas seções vamos descrever rapidamente como grande parte dos principais `geom`'s se comportam, e quais são os argumentos (ou os componentes estéticos) que podemos controlar através da função `aes()`. Dessa forma, você pode rapidamente se familiarizar com esses `geom`'s, adquirindo um vocabulário das funções que os representam, e que cobrem a maior parte dos gráficos realizados no dia-a-dia.
Lembre-se que existem várias funções `geom` diferentes disponíveis, das quais muitas não serão descritas aqui. Muitas dessas outras funções `geom` utilizam os mesmos formatos geométricos que descrevemos aqui (como linhas, retângulos, etc.), entretanto, desenham esse formato geométrico de uma maneira diferente, além de possuírem outros componentes estéticos que podem ser controlados pelo *aesthetic mapping* do gráfico.
Caso você não encontre aqui, o formato geométrico que está procurando, ou a função `geom` que realiza o desenho da forma como você deseja, você pode consultar a lista completa de funções `geom` na página oficial do pacote^[https://ggplot2.tidyverse.org/reference/index.html]. A página não possui uma versão em português, porém, você deve se virar razoavelmente bem com ferramentas de tradução (como o Google Tradutor) nessas situações. Se isso não for suficiente, você talvez encontre suas dúvidas em outros materiais construídos por brasileiros, como o blog *Curso R*^[https://www.curso-r.com/material/ggplot/], o material do departamento de Estatística da UFPR^[http://www.leg.ufpr.br/~walmes/cursoR/data-vis/index.html], ou dentro de alguma pergunta postada na página em português do *StackOverflow*^[https://pt.stackoverflow.com/].
O *R Graph Gallery*^[https://www.r-graph-gallery.com/] também é um excelente repositório (em inglês) que possui vários exemplos dos mais diversos `geom`'s, e que serve como a referência perfeita para os momentos em que você não lembra qual o `geom` que desenha o tipo de gráfico que você está procurando.
### Gráficos de dispersão e gráficos de bolha
Gráficos de dispersão são formados por `geom_point()`. Esse `geom` (por padrão) não transforma os seus dados, ou em outras palavras, ele não busca resumi-los de alguma maneira. Cada ponto desenhado no plano cartesiano representa cada uma das linhas presentes em sua base de dados. Os `geom`s que possuem este comportamento, são comumente chamados de `geom`'s individuais. Por este padrão, você deve obrigatoriamente definir as variáveis de ambos os eixos (x e y), neste `geom`.
Nos exemplos abaixo, estou utilizando a tabela `mpg` que vêm junto do `ggplot`, e nos apresenta dados de consumo de combustível de diversos modelos de carro, para mais detalhes desses dados, execute `?mpg` no console. Os gráficos nos mostram uma relação aparentemente negativa entre volume ocupado pelos pistões no motor (`displ`), e a quilometragem por litro de gasolina (`hwy`).
Após definir os eixos, você pode pintar os pontos de acordo com uma terceira variável, por exemplo, a classe do carro (compacto, SUV, minivan, ...), através do argumento *color*. A classe do carro é uma variável categórica, e por isso, o `ggplot()` irá buscar cores contrastantes para pintar os pontos. Mas você também pode definir uma variável contínua a este argumento, onde neste caso, o `ggplot()` irá criar um gradiente de cores para pintar os pontos. Uma outra possibilidade deste `geom`, é variar o formato dos pontos através do argumento *shape*.
A partir de `geom_point()` você também pode construir um gráfico de bolha, através do argumento *size*. Este tipo de gráfico em geral, piora o *overplotting*, ou a sobreposição dos pontos, já que alguns ficam muito grandes. Nestas situações, o argumento *alpha* é bem útil, sendo ele definido por um número de 0 a 1, indicando uma porcentagem de opacidade do `geom`. Por padrão, ele é configurado para 1 (100%), já no exemplo, eu reduzo essa opacidade para 40%.
```{r}
ggplot(data = mpg) +
geom_point(aes(x = displ, y = hwy))
```
```{r}
ggplot(data = mpg) +
geom_point(aes(x = displ, y = hwy, color = class))
```
```{r}
ggplot(data = mpg) +
geom_point(aes(x = displ, y = hwy, color = class, shape = drv))
```
```{r}
ggplot(data = mpg) +
geom_point(aes(x = displ, y = hwy, size = cyl), alpha = 0.4)
```
Você pode se aproveitar do componente *shape* para diferenciar, ou destacar as bordas dos pontos, ao escolher o *shape* 21. Este método é esteticamente atraente, e fica muito bom em conjunto com linhas. Dessa forma, você pode pintar o interior dos pontos de uma cor, utilizando *fill*, e a borda desse ponto de outra cor, utilizando *color*. Lembre-se que isso só é possível, pelo *shape* que escolhemos para estes pontos, em outras situações, você poderá colorir pontos apenas com uma cor, utilizando o *color*. No exemplo abaixo, eu deixo todos os três argumentos de fora de `aes()`, dessa forma, o `ggplot` mantém os valores que dei a cada um deles, constantes ao longo de todo o gráfico.
```{r}
ggplot(data = mpg) +
geom_point(
aes(x = displ, y = hwy),
shape = 21,
color = "black",
fill = "steelblue"
)
```
### Gráficos de barra
Como descrevi anteriormente, os gráficos de barras no `ggplot()` são formados pelo `geom_bar()`, e em geral, são utilizados para apresentar estatísticas que resumem os dados em poucos números (como totais, médias, medianas). Em outras palavras, os `geom`'s que tem este comportamento, buscam representar várias observações de sua base, com um único formato geométrico, e são comumente chamados de `geom`'s coletivos. Por essa razão, o argumento *stat* é importante neste `geom`, pois nele você pode conceder o valor *identity*, que evita este comportamento, e faz com que o `geom` apenas identifique os valores que você fornece a ele.
No `ggplot`, este `geom` foi criado com o intuito de permitir que o usuário construa rapidamente gráficos de contagens e somatórios. Portanto, este `geom` possui mecanismos para calcular essas estatísticas, você não precisa calculá-las por conta própria antes de gerar o `ggplot`. Por padrão, este `geom` calcula inicialmente uma contagem dos seus dados. Logo, caso você não defina qual a estatística que deseja mostrar, ele irá contar a quantidade que cada valor aparece na base. Por exemplo, o gráfico abaixo nos mostra que dentro da tabela `mpg`, temos em torno de 80 modelos com motores de 4 ou 6 cilindradas, e menos de 10 modelos com 5 cilindradas.
```{r,size = "footnotesize"}
ggplot(
data = mpg,
aes(x = cyl)
) +
geom_bar()
```
Tendo essas considerações em mente, você tem duas opções básicas ao lidar com este `geom`: 1) fornecer diretamente os dados, e pedir ao `geom` que calcule as estatísticas que você deseja mostrar (contagem ou somatório); ou 2) você primeiro calcula as estatísticas que deseja, e pede ao `geom` que apenas as identifique, sem realizar nenhuma transformação desses dados. Caso opte pela opção 2, você deve **tomar muito cuidado** com o argumento `stat = "identity"`, por razões que vou explicar abaixo.
Este `geom` não possui um mecanismo próprio para calcular médias (e muitas outras estatísticas), e portanto, se você quiser mostrá-las utilizando este `geom`, você terá de calcular separadamente essas médias, e pedir ao `geom` que apenas as identifique com `stat = "identity"`.
```{r}
medias <- mpg %>%
group_by(cyl) %>%
summarise(media = mean(hwy))
ggplot(
data = medias,
aes(x = cyl, y = media)
) +
geom_bar(stat = "identity")
```
Porém, caso você queira calcular o total, ou o somatório em cada grupo, você pode apenas definir a coluna com os valores a serem somados, para o argumento *weight* dentro de `aes()`.
```{r}
ggplot(
data = mpg,
aes(x = cyl, weight = hwy)
) +
geom_bar()
```
Agora, lembra quando eu disse que você pode pedir ao `geom` que apenas "identifique" os valores de sua base (com `stat = "identity"`) ? Com este argumento, o `geom_bar()` irá ter um comportamento diferente, caso os valores em cada grupo não sejam únicos. No exemplo anterior, em que calculei as médias de cada `cyl` em `mpg`, o `geom` apenas identificou as médias de cada `cyl`, pois há apenas **uma única** média para cada `cyl`. No exemplo abaixo, estou criando rapidamente uma tabela, e nela você pode perceber que há dois valores para o grupo `"c"`. Agora, repare o que acontece no gráfico, o `geom_bar()` acaba somando estes valores.
```{r}
tab <- data.frame(
grupo = c("a","b","c","c","d"),
valor = c(1,2,3,2,2)
)
ggplot(tab, aes(x = grupo, y = valor)) +
geom_bar(stat = "identity")
```
Em outras palavras, se os seus dados estiverem **agrupados**, o `geom_bar()` com `stat = "identity"` irá de fato apenas identificar estes valores. Mas caso os seus dados estiverem desagregados, com mais de um valor por grupo, o `geom_bar()` irá somar estes valores. Isso significa, que `stat = "identity"` representa uma outra alternativa (além de *weight*), para criar gráficos de somatório. Bastaria fornecer a coluna com os valores a serem somados para o eixo y em `aes()`, e adicionar `stat = "identity"` à `geom_bar()`.
Um outro ponto importante neste `geom`, é o posicionamento das barras. Por padrão, o `geom` empilha barras que ocupam o mesmo valor no eixo x no gráfico. Isso nos permite visualizarmos a participação dos grupos de uma outra variável categórica (cor de pele, faixa etária, ...), em cada valor presente no eixo x. Por outro lado, você talvez esteja interessado na diferença entre os grupos, e não a sua participação. Logo, você talvez queira jogar essas barras uma do lado da outra, e para isso você deve utilizar o argumento *position*, dando o valor *"dodge"*. No exemplo abaixo, retorno a base de dados `datasus`, com o objetivo de mostrar a diferença em cada cor de pele, da média de vítimas para cada sexo.
```{r, message=FALSE}
medias <- datasus %>%
group_by(Cor, Genero) %>%
summarise(media = mean(Contagem))
ggplot(
data = medias,
aes(x = Cor, y = media, fill = Genero)
) +
geom_bar(stat = "identity", position = "dodge")
```
Portanto, caso você não definisse *position* para *dodge*, o `ggplot` iria empilhar essas barras (azul e vermelho) uma em cima da outra. Em um gráfico de médias como o acima, não faria muito sentido empilhar essas barras, porém, este posicionamento faz muito sentido em gráficos de somatório, como os que fizemos na seção 8.3. Pois dessa forma você consegue visualizar o quanto que cada grupo representa do total.
Você talvez queira ir um pouco além, e observar as diferenças na participação de cada cor de pele, ao longo dos totais de vários grupos. Para isso, você pode dar o valor *fill* ao argumento *position*. Dessa forma, o `ggplot` calcula qual é a proporção de cada grupo para cada valor do eixo x, em uma escala de 0 a 1. Nesta situação, você deve definir a variável do eixo y, para o argumento *weight* em `aes()`.
```{r}
ggplot(
data = datasus,
aes(x = `Faixa etaria`, weight = Contagem, fill = Cor)
) +
geom_bar(position = "fill")
```
### Gráficos de linha
Gráficos de linha são muito utilizados em séries temporais, para mostrar a evolução de algum índice ao longo do tempo. Este tipo de gráfico é criado pelo `geom_line()`, que possui um comportamento de "conector".
O `geom_line()` (diferentemente de seu irmão `geom_path()`) sempre ordena os valores da base (antes de conectá-los), segundo a variável alocada no eixo x, na ordem que seja mais lógica para essa variável. Veja o exemplo abaixo, onde dou um vetor de datas (fora de ordem) para o eixo x. Independente da ordem em que os valores estiverem em sua base, a função irá reordenar a base antes de conectar os pontos.
```{r}
tab <- data.frame(
dia = as.Date(c("2020-01-01","2020-01-04","2020-01-02","2020-01-03")),
valor = c(10,27,14,23)
)
ggplot(tab, aes(dia, valor)) + geom_line()
```
Isso significa, que este `geom` funciona com qualquer variável no eixo x que possua uma ordem lógica, seja ela contínua ou categórica. Veja no exemplo abaixo, onde eu substituo a coluna `dia`, por um simples vetor de texto. Ao detectar o tipo de dado presente na coluna, a função reordena os valores de acordo com a ordem lógica para este tipo de dado (no exemplo abaixo, ordem alfabética).
```{r}
tab$dia <- c("a","c","d","b")
ggplot(tab, aes(dia, valor, group = 1)) + geom_line()
```
Conhecer essa funcionalidade é importante, ao fornecer para o `geom` dados dos quais ele não consegue reconhecer o formato e a ordem correta. Pense por exemplo, se você fornecesse um vetor de datas, mas no formato "abril/2020". Como os valores começam por um nome, ele reconhece estes valores como texto, e, portanto, ordena-os em ordem alfabética, ao invés de ordená-los como meses do ano. Nessas situações, transformar esses valores para fatores, e definir a sua ordem em seu atributo `levels`, é a melhor alternativa.
```{r}
tab$dia <- c("Janeiro/2020", "Abril/2020", "Fevereiro/2020", "Março/2020")
ordem <- c("Janeiro/2020", "Fevereiro/2020", "Março/2020", "Abril/2020")
ggplot(
tab,
aes(factor(dia, levels = ordem), valor, group = 1)
) +
geom_line()
```
Eu costumo aumentar a grossura dessas linhas através do argumento *size*, que por padrão está configurado para 0.5. Geralmente 1 já é um bom nível para mim, mas você pode aumentar o quanto quiser. Como eu quero que a grossura, permaneça constante ao longo de toda a linha, eu mantenho o argumento *size* de fora do `aes()`. Isso significa que você poderia variar essa grossura ao longo da linha, apesar de que o resultado seria um tanto esquisito. Tente por exemplo, adicionar ao `aes()` do exemplo anterior, o valor `size = valor`, e veja o resultado.
Neste `geom`, o argumento *group* em `aes()` é muito importante. Este argumento controla como o `geom` considera os grupos da base, na hora de desenhar o formato geométrico em questão. No primeiro exemplo dessa seção, nós não utilizamos este argumento, pois a variável ligado ao eixo x (`dia`) era uma variável contínua. Entretanto, no instante em que mudamos os valores dessa coluna para texto, tivemos que adicionar um `group = 1` ao `aes()`. Logo, quando você ligar uma variável contínua ao eixo x, muito provavelmente você não precisará mexer com o *group*. Caso a variável seja categórica, é certo que algum valor deve ser dado ao argumento *group*.
Isso é apenas uma simplificação, que serve como um guia inicial, mas que nem sempre se aplica. Pois o *group* não diz respeito ao tipo de variável (contínua ou categórica), e sim se você quer separar ou não as linhas por algum agrupamento. Se você está apenas querendo mostrar uma única linha no gráfico, essa simplificação será útil. Mas com o tempo você vai se pegar utilizando o *group*, para mostrar em um mesmo gráfico a evolução de vários índices diferentes ao longo do tempo, mesmo que a variável no eixo x (datas) seja uma variável contínua. Basta relembrar o exemplo da seção 8.4, em que utilizamos *linetype* para diferenciar as curvas de três indicadores diferentes em um mesmo `geom_line()`. Você poderia replicar o mesmo gráfico utilizando *group*, ao invés do *linetype*.
Essa questão fica mais clara, ao utilizarmos uma base que possui mais de um valor por grupo. Veja por exemplo a base `Oxboys`, que vem do pacote `mlmRev`. Essa base é resultado de uma pesquisa, onde os pesquisadores acompanharam durante vários anos, o crescimento de alguns indivíduos.
```{r}
head(mlmRev::Oxboys, n = 10)
```
Portanto, a coluna `Subject` identifica qual o indivíduo os valores da linha se referem. Repare que várias linhas dizem respeito ao mesmo indivíduo. Agora, pense como o `geom_line()` trataria esses diversos valores que se encaixam no mesmo grupo (no nosso caso, no mesmo `Subject`). Neste caso, o `geom_line()` irá conectar (incorretamente) todos os valores em conjunto da base, pois ele não sabe que cada um desses valores pertence a sujeitos diferentes, o `geom` pensa que todos esses valores pertencem a um único sujeito. O resultado seria um gráfico com um aspecto de "serra".
```{r, include=FALSE}
Oxboys <- mlmRev::Oxboys
```
```{r}
ggplot(
Oxboys,
aes(x = age, y = height)
) +
geom_line()
```
Para que isso fique claro, eu adicionei um `geom_point()` para que você veja cada um dos valores presentes na base. Primeiro, preste atenção nas variáveis que conectamos aos eixos do gráfico (idade e altura do indivíduo). Ambas as variáveis são contínuas, mas neste momento, não há qualquer variável no gráfico que possa identificar a qual dos indivíduos, cada um desses valores se refere. Logo, o `geom_line()` acaba conectando todos esses pontos juntos.
```{r}
ggplot(
Oxboys,
aes(x = age, y = height)
) +
geom_line() +
geom_point()
```
Ao invés do `geom_line()` conectar todos esses pontos em conjunto, o `geom` deveria conectar todos os pontos que dizem respeito ao mesmo indivíduo, e é para isso que o argumento `group` serve. Você define neste argumento, qual a coluna que identifica qual é o grupo (ou no nosso caso, o indivíduo) que está sendo tratado em cada observação de sua base de dados.
```{r}
ggplot(
Oxboys,
aes(x = age, y = height, group = Subject)
) +
geom_line() +
geom_point()
```
Uma outra forma de definirmos esses grupos para o `geom`, é colorindo as linhas com o argumento *color*, ou então variando o formato dessas linhas com o argumento *linetype*. Basta você fornecer a estes argumentos, uma coluna que seja capaz de identificar cada um dos grupos ou indivíduos (no nosso caso, `Subject`) que estão sendo tratados no gráfico.
```{r}
ggplot(
Oxboys,
aes(x = age, y = height, color = Subject)
) +
geom_line()
```
Portanto, toda vez em que utilizar este `geom` em uma base que possui mais de um valor por grupo, você muito provavelmente terá de utilizar *group*, especialmente se você precisa diferenciar as curvas de cada grupo no gráfico.
Se você quiser mostrar uma única linha no gráfico, você vai mexer obrigatoriamente com o *group* caso a variável do eixo x seja categórica, onde neste caso, você deve dar uma constante qualquer ao argumento (eu geralmente defino para 1: `aes(group = 1)`). Isso é necessário, porque `geom_line()` entende que cada um dos valores dessa variável categórica, representa um grupo diferente. Dessa forma, cada um desses grupos irá possuir apenas um valor em toda a base. Caso você se esqueça de definir este valor para *group* nesta situação, o seguinte erro irá aparecer:
```{r, eval = FALSE, highlight = FALSE}
# Each group consists of only one observation. Do you need to adjust the group
# aesthetic?
```
### Histogramas e outros gráficos de frequência
Histogramas e polígonos de frequência são gráficos "unidimensionais", ou dito de outra forma, apresentam informações sobre apenas uma variável, mais especificamente uma variável contínua. Por essa razão, você precisa definir apenas um dos eixos do gráfico, geralmente, o eixo x. Estes gráficos são criados por `geom_histogram()` e `geom_freqpoly()`.
```{r}
ggplot(mpg, aes(hwy)) + geom_histogram()
ggplot(mpg, aes(hwy)) + geom_freqpoly()
```
Ambos os gráficos funcionam da mesma forma, apenas a forma geométrica utilizada é diferente. Eles pegam a distribuição da variável ligada ao eixo x, e dividem essa distribuição em vários intervalos (chamados de *bin*'s), e contam quantos valores se encaixam em cada um destes intervalos. Neste `geom`, é importante que você teste diferentes larguras para estes intervalos, através do argumento *binwidth*. Por padrão, o `geom` tenta dividir a distribuição em 30 intervalos diferentes.
Você pode separar as distribuições por alguma variável categórica, dando essa variável ao argumento *group*. Porém, essas distribuições estarão sobrepostas no gráfico, sendo impossível diferenciá-las. Logo, é necessário que você mostre essas distribuições separadas em diferentes facetas do gráfico (através da função `facet_wrap()`).
```{r}
ggplot(mpg, aes(hwy, group = cyl)) +
geom_histogram() +
facet_wrap(~class)
```
O `geom_freqpoly()` não sofre seriamente deste problema, pois a sua forma geométrica é "oca". Mas é interessante de qualquer forma, que você ou separe essas distribuições em diferentes facetas do gráfico, ou então, que colora as distribuições de acordo com a variável categórica utilizada.
```{r}
ggplot(mpg, aes(hwy, color = class)) +
geom_freqpoly()
ggplot(mpg, aes(hwy, fill = class)) +
geom_histogram() +
facet_wrap(~class)
```
Uma alternativa a estes `geom`'s, é o `geom_density()` que calcula uma função de densidade para a variável escolhida. Caso esteja interessado em separar essa distribuição de acordo com uma variável categórica, eu recomendo que dê uma olhada no pacote `ggridges`. Este pacote fornece novos `geom`'s, que posicionam essas distribuições separadas de uma forma esteticamente atraente, sem a necessidade de construir diferentes facetas do mesmo gráfico, além de fornecer mecanismos para marcar os percentis da distribuição no gráfico. É mais fácil ver com seus próprios olhos ^[Veja a página oficial do pacote: https://cran.r-project.org/web/packages/ggridges/vignettes/introduction.html], do que eu explicar.
Caso você prefira permanecer com o `geom` padrão do `ggplot` e ainda separar a distribuição por uma variável categórica, você pode utilizar o argumento *alpha* para reduzir a opacidade dessas distribuições, como um meio de combater a sobreposição. Mas o ideal, é que você as separe em diferentes facetas, utilizando `facet_wrap()` da mesma forma que fizemos para os histogramas.
```{r}
ggplot(mpg, aes(hwy, fill = class)) + geom_density(alpha = 0.4)
```
### Adicionando textos ao gráfico
Você pode adicionar rótulos ao seu gráfico com `geom_label()`, ou adicionar textos simples com `geom_text()`. Estes `geom`'s funcionam exatamente como o `geom_point()`, porém, ao invés de desenharem pontos, eles desenham textos. Em outras palavras, eles são `geom`'s individuais, em que desenham um texto, ou um rótulo, para cada uma das observações de sua base de dados.
Dessa vez, você deve definir a coluna que contém os rótulos/textos que deseja mostrar no gráfico, no argumento *label* em `aes()`. Os rótulos serão posicionados no plano cartesiano de acordo com os valores definidos pelas variáveis ligadas aos eixos x e y.
```{r}
ggplot(mpg, aes(x = displ, y = hwy, label = model)) +
geom_text()
ggplot(mpg, aes(x = displ, y = hwy, label = model)) +
geom_label()
```
Ao colocar textos em um gráfico, você dificilmente não enfrentará algum nível de sobreposição. O `ggplot` oferece algumas ferramentas que em muitas ocasiões não resolvem o problema, mas que em outras podem ser suficientes. Ambos os `geom`'s descritos aqui, possuem o argumento *check_overlap*. Caso ele seja configurado para `TRUE`, o `ggplot` irá criar os rótulos na ordem em que eles aparecem na sua base, e eliminar todos os rótulos consecutivos que sobreporem os anteriores. O código ficaria dessa forma:
```{r, eval = FALSE}
ggplot(mpg, aes(x = displ, y = hwy, label = model)) +
geom_text(check_overlap = TRUE)
```
Apesar de uma solução, ela pode muito bem eliminar justamente os rótulos que queremos destacar no gráfico, e por isso é pouco desejada. Você poderia também reduzir o tamanho da fonte através de *size*. Um detalhe é que este argumento trabalha por padrão com valores em milímetros (mm), mas como é um pouco confuso trabalhar com tamanho de fontes nesta unidade, eu geralmente transformo os valores para pontos (pt). No exemplo abaixo, estou reduzindo o tamanho das fontes para 7 pt. O problema dessa opção, é que ela representa um *trade-off* entre a sobreposição de pontos, e a legibilidade dos rótulos, cabe a você definir o equilíbrio entre essas opções.
```{r}
ggplot(mpg, aes(x = displ, y = hwy, label = model)) +
geom_text(size = 7/.pt)
```
A melhor solução possível, seria ajustarmos a posição de cada um dos pontos individualmente. Entretanto, se você tem vários textos que exigem desvios diferentes, essa solução facilmente se torna muito trabalhosa. A ideia, seria criarmos duas novas colunas em nosso `data.frame`, onde em cada uma você define um valor de desvio vertical (`y_desvio`), e na outra o valor de desvio horizontal (`x_desvio`) para o rótulo definido naquela linha. Em seguida, você conecta essas colunas aos argumentos de posição responsáveis por realizar estes deslocamentos de textos (*nudge_y* e *nudge_x*) em seu *aesthetic mapping* (`aes()`). Veja o código abaixo.
```{r, eval = FALSE}
ggplot(
mpg,
aes(
x = displ,
y = hwy,
label = model,
nudge_x = x_desvio,
nudge_y = y_desvio
)) +
geom_text()
```
Vamos separar uma seção para descrevermos outras soluções mais eficazes para esse problema. Também vamos separar, uma seção para descrevermos quais são as estratégias possíveis para você trocar a fonte dos textos mostrados no gráfico, algo que ainda é difícil de ser realizado, especialmente se você trabalha no Windows. Agora vou explicar o que os argumentos de posição (*nudge_x* e *nudge_y*), e os de justificação (*hjust* e *vjust*) fazem.
Durante muito tempo, eu sofri de uma leve confusão entre esses argumentos. Como você muito provavelmente vai querer ajustar o posicionamento desses textos, vou tentar explicar a diferença entre os dois da forma mais clara possível, para que você não sofra do mesmo efeito.
Vamos começar pelos argumentos de justificação, que são *hjust* (justificação horizontal) e *vjust* (justificação vertical). Estes argumentos, servem para alterar a justificação, ou o alinhamento da cadeia de texto em relação ao seu ponto de referência (ou de coordenadas).
```{r}
df <- data.frame(
x = c(1, 1, 2, 2, 1.5),
y = c(1, 2, 1, 2, 1.5),
text = c(
"bottom-left", "bottom-right",
"top-left", "top-right", "center"
)
)
ggplot(df, aes(x, y)) +
geom_point(color = "darkgray", size = 7) +
geom_text(aes(label = text))
```
Por padrão, *hjust* é configurado para *center*, e *vjust* para *middle*. Logo, todos os rótulos são centralizados (tanto verticalmente, quanto horizontalmente) no ponto que define a sua localização. Para mudar o alinhamento de todos os rótulos de uma vez, você pode configurar estes argumentos, por fora do `aes()`, fornecendo um dos valores pré-definidos.
No caso de *hjust*, há outros quatro valores pré-definidos possíveis (*left, right, inward, outward*). Caso você coloque *left* ou *right* neste argumento, todos os rótulos serão alinhados à esquerda, ou à direita dos pontos. Porém, caso você coloque *inward* ou *outward*, os textos serão alinhados (horizontalmente em relação aos pontos de sua localização) em um sentido para o para o centro do gráfico, ou se afastando do centro do gráfico. Dito de outra forma, os textos serão alinhados à esquerda, ou à direita do ponto de referência, a depender da sua localização em relação ao centro do plano cartesiano e do sentido escolhido (*inward* ou *outward*).
Para *vjust*, há também quatro outros valores pré-definidos (*bottom, top, inward, outward*). Os valores *bottom* e *top* alinham os textos na base ou no topo do ponto de referência do texto. Enquanto os valores *inward* e *outward* funcionam no mesmo sentido que em *hjust*, porém eles controlam o alinhamento vertical dos textos.
```{r}
ggplot(df, aes(x, y)) +
geom_point(color = "gray", size = 7) +
geom_text(aes(label = text), vjust = "inward", hjust = "inward")
```
Para deixar claro o que estes argumentos fazem, trago um novo exemplo abaixo que contém cadeias de texto de duas linhas. Caso você queira variar a justificação destes textos, ao longo do gráfico, significa que você deve conectar uma coluna de seu `data.frame` a estes argumentos em `aes()`. Porém, estes argumentos não aceitam os valores pré-definidos ao estarem dentro de `aes()`. Nestas situações, você deve fornecer um número: 0 (justificado à esquerda); 0.5 (centralizado); ou 1 (justificado à direita).
```{r}
tab <- data.frame(
y = rep(1:3, times = 3),
x = rep(1:3, each = 3),
texto = rep(c("Um texto alinhado\nà esquerda",
"Um texto\ncentralizado",
"Um texto alinhado\nà direita"),
each = 3
),
hjust = rep(c(0, 0.5, 1), each = 3),
vjust = rep(c(0, 0.5, 1), times = 3)
)
ggplot(tab, aes(x, y)) +
geom_point(size = 7, color = "darkgray") +
geom_text(aes(
label = texto,
hjust = hjust,
vjust = vjust
))
```
Eu acredito que é justamente essa opção numérica, que gera toda a confusão sobre a função verdadeira destes argumentos. Pois o `ggplot` não gera nenhum erro caso você dê valores diferentes, e se você aumentar progressivamente estes valores, você irá perceber que o deslocamento dos textos também aumenta. Muitos que se deparam com este comportamento, podem acreditar que estes argumentos servem para deslocar os textos, e não para alinhá-los em relação ao ponto de suas coordenadas. Por isso eu recomendo nestes argumentos, que você utilize um dos valores pré-definidos que citei anteriormente, e utilize essa escala numérica, apenas em situações em que você precisa dessa variação utilizando `aes()`.
Uma outra razão pela qual estes argumentos não são apropriados, caso você queira deslocar os textos em um sentido, é que eles não trabalham em sintonia com as escalas dos eixos. No exemplo abaixo, eu configuro o valor de *vjust* para -4. Porém, o `ggplot` não deslocou verticalmente os textos em 4 unidades. O texto de valor *center*, por exemplo, não foi deslocado para as coordenadas (x = 1.5, y = 5.5), e se você quiser que ele chegue nessa coordenada? O que você faz? Triplica? Quadruplica o valor anterior? Tudo isso, significa que não há como você prever o quanto o texto irá deslocar, e por isso, você pode perder muito tempo testando diversos valores em um argumento inadequado para o resultado que deseja.
```{r}
ggplot(df, aes(x, y)) +
geom_point(color = "gray", size = 7) +
geom_text(aes(label = text), vjust = -4)
```
Agora, vou explicar como os argumentos de posição funcionam. Como o próprio sufixo deles dá a entender, o *nudge_y* irá deslocar verticalmente os textos, e *nudge_x*, vai deslocá-los horizontalmente. O verbo *nudge* em inglês se refere ao ato de "cutucar", ou empurrar gentilmente alguém, logo, estes argumentos servem para "empurrar" os textos de suas posições originais no plano cartesiano. Para demonstrarmos a sua aplicação, vamos tentar rotular um gráfico de barras, que apresente um somatório da quilometragem em cada cilindro.
Como descrevi anteriormente, o `geom_bar()` é um `geom` coletivo, enquanto os `geom`'s de texto são `geom`'s individuais. Por isso, caso você adicionar diretamente um `geom_text()` ao `geom_bar()`, sem levar em conta essa diferença, ele irá rotular cada uma das observações da base resumidas em cada barra, e não o total que ela representa.
Para rotular corretamente essas barras, você tem duas opções: 1) calcular o somatório em um objeto separado, e em seguida fornecer este objeto ao argumento *data*, e ajustar o *aesthetic mapping* de acordo com este objeto, em `geom_text()`; ou 2) usar as transformações estatísticas que o `ggplot` já disponibiliza para esse trabalho. No exemplo abaixo, estou demonstrando a opção 1, mas darei um exemplo da opção 2 quando chegarmos à seção de transformações estatísticas do `ggplot`.
```{r}
somatorios <- mpg %>%
group_by(cyl) %>%
summarise(soma = sum(hwy))
ggplot() +
geom_bar(
mapping = aes(x = cyl, weight = hwy),
data = mpg
) +
geom_text(
mapping = aes(x = cyl, y = soma, label = soma),
data = somatorios
)
```
Portanto, neste exemplo as duas camadas de `geom` utilizam não apenas *aesthetic mapping*'s, mas também fontes de dados, diferentes. Como você pode reparar acima, os rótulos estão sobre o topo da barra. Por isso, eu posso utilizar o *nudge_y* para adicionar um pequeno desvio vertical nestes rótulos, dando assim um maior espaço entre ele e a barra.
Diferentemente dos argumentos de alinhamento, os argumentos de posição (*nudge_y* e *nudge_x*) funcionam em sintonia com a escala dos eixos. Como a escala do eixo y termina em aproximadamente 2500, um desvio de 100 é provavelmente suficiente. Isso significa que caso o limite dessa escala fosse 1 décimo disso (250), por exemplo, um desvio de 100 em *nudge_y* iria gerar um deslocamento considerável nestes rótulos.
```{r}
ggplot() +
geom_bar(
mapping = aes(x = cyl, weight = hwy),
data = mpg
) +
geom_text(
mapping = aes(x = cyl, y = soma, label = soma),
data = somatorios,
nudge_y = 100
)
```
Além dessas opções, caso você insira textos de 2 ou mais linhas no gráfico, você pode se interessar em reduzir ou aumentar o espaço entrelinhas destes textos. Neste caso, você pode controlar este espaço pelo argumento *lineheight* que define a proporção em relação à altura das letras. Um outro ponto possível de customização, é o ângulo dos textos, que é definido pelo argumento *angle*. Neste argumento, basta fornecer um número (de 0 a 360) que represente o ângulo desejado.
```{r}
ggplot() +
geom_bar(
mapping = aes(x = cyl, weight = hwy),
data = mpg
) +
geom_text(
mapping = aes(x = cyl, y = soma, label = soma),
data = somatorios,
nudge_y = 100,
angle = 45
)
```
## Exportando os seus gráficos do `ggplot` {#sec:devices_graficos}
Após gerar os seus gráficos com o `ggplot`, você provavelmente vai querer exportá-los para algum arquivo de imagem, para que você possa inseri-los em seu artigo em Word (`.docx`), ou em seu PowerPoint (`.pptx`) que você deve apresentar ao seu chefe no dia seguinte. Para realizarmos essa tarefa, precisamos utilizar funções que possam construir esses arquivos de imagem, nos quais podemos guardar os nossos gráficos. Com isso, temos duas alternativas mais comuns no R, que são:
1) através da função `ggsave()`, que é exposta por \citeonline[Seção 8.5]{wickham2016}.
2) utilizando o método tradicional de se exportar gráficos no R, descrita por \citeonline[Cáp. 1]{murrell2006}.
Uma outra referência que também descreve ambas alternativas, se encontra em \citeonline[Cáp. 14]{chang2012}. A primeira alternativa citada, seria uma forma mais prática de se exportar os seus gráficos no R, através da função `ggsave()` (que vem do próprio pacote `ggplot`). Entretanto, essa função nada mais é, do que um *wrapper* sobre as funções do pacote `grDevices`, que são utilizadas na segunda alternativa citada acima. Ou seja, a função `ggsave()` é apenas um atalho para o método descrito por @murrell2006.
Em mais detalhes, o pacote `grDevices` (que está incluso nos pacotes básicos da linguagem) oferece um conjunto de funções capazes de acessar diversos *devices* gráficos. Cada *device* gráfico, representa uma *engine* diferente que vai ser responsável por construir o arquivo onde o seu gráfico será guardado. Portanto, cada uma dessas *engines*, vão gerar um tipo arquivo diferente, ou em outras palavras, arquivos de extensões diferentes. Você já utiliza muitos desses *devices* gráficos, praticamente o tempo todo em sua rotina. Você apenas não sabia, que esse era o nome técnico dado às *engines*, que normalmente constroem esses tipos de arquivos. Sendo os exemplos mais famosos, os arquivos: JPEG/JPG (`.jpeg`, `.jpg`), PNG (`.png`), SVG (`.svg`) e PDF (`.pdf`).
### Tipos de representação geométrica em *devices* gráficos
Ao longo das últimas décadas, a área da computação gráfica desenvolveu diversos modelos computacionais que fossem capazes de representar visualmente e virtualmente, o nosso mundo real [@hughes2014]. Com isso, eu quero destacar que nós possuímos hoje, formas diferentes de se representar uma mesma imagem em nosso computador.
Isso significa, que cada um dos *devices* gráficos disponíveis, que podemos utilizar para guardar os nossos gráficos no R, utilizam um modelo ou método de representação geométrica diferente para representar a sua imagem. Cada um desses modelos, possuem características diferentes, e com isso, incorrem em erros distintos na representação virtual de sua imagem. Logo, conhecer, mesmo que de maneira sutil, esses modelos de representação, as suas vantagens e características, se torna importante para fundamentarmos as nossas decisões sobre como vamos salvar os nossos gráficos no R.
Nós temos atualmente, dois modelos principais de representação geométrica que são utilizados para representar imagens, ao longo de toda a indústria da computação gráfica, sendo elas:
1) Vetorial.
2) Matricial.
A representação vetorial (figura 8.3), como o próprio nome dá a entender, busca conectar um conjunto de vetores (ou de linhas) para formar cada forma geométrica presente em sua imagem. Um arquivo de imagem que utiliza essa representação, possui uma descrição matemática dos elementos geométricos que compõe a sua imagem [@murray1996]. Essa descrição matemática possui informações como a direção, o comprimento e as coordenadas dos vetores (ou linhas) que formam cada forma geométrica de sua imagem.
Em outras palavras, a representação vetorial funciona como aqueles desenhos infantis de "conecte os pontos". Nesse sistema, qualquer forma presente em nosso gráfico, seja ela um quadrado, um círculo, uma letra, ou uma garrafa, é formada por um conjunto de linhas que conectam os "vértices" de cada forma.
```{r, echo = F, fig.cap="Diferenças entre as representações vetorial e matricial"}
knitr::include_graphics("Figuras/vetorial_matricial.png")
```
Por outro lado, imagens que se encontram em representação matricial (figura 8.3), são popularmente conhecidas por *raster image*, ou *bitmap image*, e utilizam-se de uma malha quadricular (ou de um *grid*), no qual cada célula é preenchida, a fim de representar cada parte de sua imagem. Uma forma típica de identificarmos esse tipo de representação, está no efeito "escada", ou no efeito pixelado (ou quadriculado) que adquirimos ao darmos um *zoom* nesse tipo de imagem.
Os principais *devices* gráficos disponíveis no R, que utilizam a representação vetorial, são os que constroem arquivos PDF (`.pdf`) e SVG (`.svg`). Além desses, temos alguns outros *devices* menos comuns, como os arquivos *encapsulated PostScript* (`.eps`) que são mais utilizados em programas da Adobe, como o PhotoShop. Imagens produzidas através de representações vetoriais, são em geral, mais bem definidas do que imagens produzidas por representações matriciais, e, mesmo que o usuário dê um *zoom* grande sobre a imagem, elas são capazes de manter essa definição.
Logo, como foi destacado por @wickham2016 [, p 185], imagens que utilizam uma representação vetorial parecem mais atraentes em um número maior de lugares. Especialmente pelo fato, de que o sistema vetorial consegue representar formas geométricas (principalmente polígonos), de maneira mais precisa, do que o sistema matricial.
Apesar dessa vantagem, não são todos os programas que suportam o uso de imagens provenientes de representações vetoriais (por exemplo, o Word aceita o uso de arquivos SVG, mas não aceita o uso de PDF's para inserção de imagens). Em contrapartida, arquivos de *raster image* (ou *bitmap image*), são aceitos na grande maioria dos programas, e portanto, representam uma forma mais portátil de transportar os seus gráficos ao longo de diversos programas e sistemas. Os *devices* gráficos mais conhecidos, que usam a representação matricial, são os arquivos PNG (`.png`), JPEG/JPG (`.jpeg`) e TIFF (`.tiff`).
Logo, ao escolher o *device* gráfico que irá gerar o seu arquivo de imagem, você deve refletir sobre qual o formato que mais se adequa as suas necessidades. Mesmo que você possa produzir imagens mais fiéis através de uma representação vetorial, isso não se configura na maioria das ocasiões, como uma grande vantagem. Pois, você pode se aproveitar da maior flexibilidade dos *devices* de representação matricial, e ainda assim, produzir imagens muito bem definidas e de alta resolução. Sobretudo com o uso de um arquivo PNG (`.png`) ou TIFF (`.tiff`), que produzem em geral, resultados melhores do que um arquivo JPEG/JPG (`.jpeg`).
Em resumo, caso o uso de um arquivo PDF (`.pdf`), ou SVG (`.svg`), não represente uma limitação para o seu trabalho, você geralmente vai preferi-los em detrimento de outros *devices* gráficos. Entretanto, caso você precise de uma maior portabilidade de seu gráfico, você ainda pode atingir ótimos resultados com um *device* gráfico de representação matricial, como um arquivo PNG (`.png`) ou TIFF (`.tiff`). Basta que você utilize uma resolução alta, e aplique um *anti-aliasing* sobre o arquivo em que você irá salvar o gráfico. Um bom nível de resolução para esses tipos de arquivos, se encontra na casa dos 300 dpi, sendo essa a resolução mínima requisitada pela maioria dos jornais e revistas científicas.
### A função `ggsave()`
A função `ggsave()` pertence ao pacote `ggplot`, e representa um atalho útil para o método descrito por @murrell2006. Por padrão, essa função vai sempre salvar o último gráfico gerado em sua sessão. Ou seja, para utilizar essa função, você deve primeiro gerar o seu gráfico, ou melhor dizendo, o seu gráfico deve estar aparecendo na área direita e inferior do seu RStudio, na seção de `Plots`. Pois é a partir do *cache* dessa seção, que `ggsave()` irá coletar o seu gráfico, e, portanto, salvá-lo em algum local de seu computador.
Dessa forma, o código necessário para utilizar essa função é semelhante ao código abaixo. Você primeiro gera o gráfico, e, em seguida, executa a função `ggsave()` para salvá-lo.
```{r, eval = FALSE}
ggplot(mpg, aes(displ, cty)) + geom_point()
ggsave("output.pdf")
```