Last active
April 28, 2018 12:01
-
-
Save sillasgonzaga/4fa5b9aa460b6c23013e1ae35e3d7efa to your computer and use it in GitHub Desktop.
Aula 03 - Curso de Ciência de Dados com R
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- | |
title: "Aula 3: Gráficos no R" | |
output: | |
html_notebook: | |
css: custom.css | |
number_sections: yes | |
toc: yes | |
toc_float: true | |
--- | |
Pacotes usados nesta aula: | |
```{r, warning = FALSE, message = FALSE} | |
library(tidyverse) | |
library(RColorBrewer) | |
#library(reshape2) | |
library(gcookbook) | |
library(modelr) | |
library(ggiraph) | |
library(plotly) | |
library(rphylopic) | |
library(OutbreakTools) | |
library(gridExtra) | |
library(gapminder) | |
library(gganimate) # devtools::install_github("dgrtwo/gganimate") | |
library(ggmap) # devtools::install_github("dkahle/ggmap") | |
library(leaflet) | |
library(sunburstR) | |
``` | |
# base R | |
A base R tem *muitos* jeitos de fazer gráficos, afinal, R começou a ficar bem conhecido no começo por sua capacidade em fazer visualização. Toda classe de objeto tem um método próprio de fazer gráficos. | |
Por exemplo, se eu tiver um objeto no R é da classe `lm` (linear model), e digito `plot()`, o R vai criar gráficos baseado na classe de modelo linear. | |
Um exemplo: | |
```{r} | |
reg <- data_frame(y = rnorm(n = 50, mean = 5, sd = 5), | |
x1 = rnorm(n = 50, mean = 1, sd = 2)) | |
modelo <- lm(y ~ x1, data = reg) | |
``` | |
Agora eu posso usar simplesmente `plot()`. R sabe da natureza do objeto `modelo` e vai criar um gráfico appropriado. | |
```{r} | |
plot(modelo) | |
``` | |
Estes gráficos vão ser produzidos com `plot()` somente de objetos `lm`. Se eu usar outros objetos, eu vou ter outro gráfico: | |
```{r} | |
plot(reg$y, reg$x1) | |
``` | |
No R da base, a lógica dos gráficos funciona assim: todo tipo de objeto tem métodos próprios de fazer gráficos. Isso significa que: | |
- O mundo de gráficos no R é gigantesco; | |
- O que você vai produzir depende muito da sua análise. | |
<br> | |
# ggplot2 | |
Um pacote do Hadley Wickham, `ggplot2`, tem outra lógica. `ggplot2` faz parte do tidyverse e, embora que tenha uma sintaxe um pouco diferente, utiliza os mesmos princípios de "tidy data". O *gg* em ggplot2 é uma referência ao Grammar of Graphics - uma filosofia sobre visualização, de Leland Wilkinson. | |
- `ggplot2` é carregado automaticamente com `library(tidyverse)`. | |
- É o pacote mais baixado do CRAN e o mais pesquisado no StackOverflow. | |
- É tão importante que foi portado para o Python e para o Matlab. | |
**Um aviso sobre ggplot2: tantos pacotes o usam que é bom fazer update dos todos os pacotes se você faz update do ggplot2. Pode ser que você tenha que instalar versões em desenvolvimento usando `install_github()`** | |
<br> | |
A função mais importante no pacote é `ggplot()`. | |
- `ggplot()` só aceita dataframe como input; | |
- O plot é construido em **layers**; | |
- Todo layer usa um **geom**, que é o objeto visual que nós vamos usar (ponto, linha etc.). Também tem outros elementos (cores, texto) que podemos customizar. | |
- usamos o argumento `aes` (aesthetic) para **mapear** variáveis aos objetos visuais (os geoms, ou cores, ou simplesmente para eixo x e y); | |
- Cada plot é um objeto no R e pode ser salvo assim. | |
<br> | |
<br> | |
Tem bastante recurso sobre ggplot2 na internet, dado que é o pacote mais popular do R. | |
Um livro que recomendo é do Winston Chang: | |
 | |
<br> | |
O do Hadley mesmo é de graça, só tem que compilar. Mas não é o mais fácil, e já é um pouco antigo. | |
<br> | |
<br> | |
## O uso de cores | |
*Os nomes* das cores no R podem ser vistos com: | |
```{r, eval = F} | |
colors()[1:50] | |
``` | |
<br> | |
O pacote `RColorBrewer` tem umas paletas de cores. Podemos ver elas com `display.brewer.all()`. (Para mais, ver [http://www.colorbrewer.org.](http://www.colorbrewer.org.)) | |
```{r, fig.height=8} | |
# install.packages("RColorBrewer") | |
library(RColorBrewer) | |
display.brewer.all() | |
``` | |
## salvar gráficos | |
Nós vamos criar muitos gráficos hoje. Você pode salvar usando a janela dos gráficos no RStudio ("Export") ou com funções dentro do R. | |
Um gráfico que fazemos com `ggplot()` pode ser salvo ou com `ggsave()` ou usando uma das funções `bmp()`, `jpeg()`, `png()`, `pdf()` e `tiff()`, mas se você usa uma dessas, vai ter que terminar o comando com `dev.off()` para "desligar" o aplicativo. Por exemplo: | |
```{r, eval = F} | |
pdf(file = "meu_plot.pdf", width = 8, height = 10) | |
# código do gráfico | |
dev.off() | |
``` | |
<br> | |
`ggsave()` usa por default o último gráfico que está na janela do RStudio ("Plots"). Essa função pode adivinhar o tipo de arquivo que você quer da extensão que você especifica. | |
Por exemplo, se eu crio gráfico com código assim: | |
```{r, eval =F} | |
ggplot(data, aes(x, y)) + geom_point() | |
``` | |
Depois eu simplesmente digito: | |
```{r, eval = F} | |
ggsave("meu_plot.pdf") | |
ggsave("meu_plot.png") | |
``` | |
E esse gráfico vai ser salvo como .pdf e .png agora. | |
<br> | |
<br> | |
## `ggplot()` | |
Vamos conhecer a função principal do `ggplot2`. Ela tem essa estrutura: | |
ggplot(DATA, aes(x = VARIAVEL X, y = VARIAVEL Y)) + | |
geom_X + | |
geom_X2 etc. | |
onde DATA é seus dados e geom_X é um tipo de geom. É possível ver que a sintaxe é semelhante ao dplyr, só que o `ggplot2` foi criado antes do pipe ( `%>%` ) e por isso, usa `+`, mas serve para os mesmos fins. | |
## Geoms | |
| Tipos de gráfico | geom | | |
| ---------------- | ---- | | |
|scatterplot (gráfico de dispersão)| `geom_point()`| | |
| barchart (gráfico de barras) | `geom_bar()`| | |
| boxplot | `geom_boxplot()`| | |
| line chart (gráfico de linhas) | `geom_line()`| | |
| histogram (histograma) | `geom_histogram()`| | |
| density (densidade) | `geom_density()`| | |
| smooth (aplica modelo estatístico) | `geom_smooth()`| | |
... e tem mais ([http://docs.ggplot2.org/current/](http://docs.ggplot2.org/current/)). | |
<br> | |
Se você não usa um geom, R produz um gráfico vazio: | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg)) | |
``` | |
Ele sabe o que é `x` e `y`, mas nada além disso. | |
<br> | |
## Plotando de forma rápida | |
A biblioteca ggplot2 inclui a função `qplot()`, para plotar coisas de forma rápida. | |
Eu não uso isso muito, mas é fácil: | |
```{r} | |
qplot(price, carat, data = diamonds) | |
``` | |
<br> | |
<br> | |
Provavelmente o geom mais comum e mais útil é o `geom_point()`, que cria pontos. Vamos criar um "scatterplot", ou gráfico de dispersão. O gráfico de dispersão é ideal para enxergamos a relação entre duas variáveis quantitativas. | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg)) + | |
geom_point() | |
``` | |
O `geom_point()` é uma função, então pode aceitar argumentos e tem página de help como toda outra função. | |
Se você esquece o `+`, vai ignorar a linha e de novo criar nada. | |
<br> | |
<bdi style="color:#1874CD;"> | |
- Eu quero fazer o mesmo gráfico de pontos, mas com pontos da cor "dodgerblue" e de tamanho 3.5. Como eu faço? (lembra que geom_point() tem página de help) | |
- Escolha umas outras cores que você prefere e faz o mesmo gráfico. | |
</bdi> | |
<br> | |
<br> | |
<br> | |
<br> | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg)) + | |
geom_point(colour = "dodgerblue", size = 3.5) | |
# Podemos usar "color" ou "colour". | |
``` | |
Não é só nome: as cores tem código também. Por exemplo, o azul da pergunta em cima é `#1874CD`. Pode ver isso usando o Addin "Colour Picker", ou tem recursos na internet, como w3schools. Para ver os Addins: | |
```{r, eval = F} | |
install.packages('addinslist') | |
``` | |
Agora deve ter um "Addins" no topo do RStudio (talvez tenha que recomeçar RStudio). O Colour Picker é útil para escolher cores. | |
<br> | |
Além de `colour`, podemos usar `shape` e `fill`. O `fill` usa as cores como `colour`, e shape tem essas formas disponíveis: | |
 | |
Como é possível ver, umas formas aceitam uma outra cor pois são "vazias" dentro, como números 21 até 25. Números 0, 1, 2, 5, 6 etc. *parecem* vazios, mas não aceitam uma outra cor dentro. | |
Números 15, 16, 17 etc. não vão aceitar uma outra cor como `fill`, pois já são de uma cor sólida. Um outro argumento que é útil quando você usa `colour` e `fill` é `alpha`, que controle a opacidade da cor. (1 = sólido, 0 = transparente) | |
Como usar? | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg)) + | |
geom_point(colour = "navyblue", size = 3.5, | |
shape = 22, fill = alpha("blue", 0.4)) | |
``` | |
<br> | |
<br> | |
<bdi style="color:#1874CD;"> | |
Usa essa base de gráfico e altera as cores, tamanhos, e formas dos pontos. Usa fill se for possível, e muda a alpha. | |
</bdi> | |
<br> | |
## `aes()` | |
A função `aes()` é uma parte muito importante do gráfico. É essa que faz o 'mapeamento' das variáveis na base para os elementos visuais no gráfico. Antes, só fizemos esse mapeamento com `x` e `y`. Podemos fazer com a cor (que vai afetar todo geom se tivermos mais): | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp)) + | |
geom_point() | |
``` | |
<br> | |
E também podemos mapear a variável `disp` ao tamanho (size) dos pontos: | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() | |
``` | |
<br> | |
Como podemos usar cores que queremos? Com um outro *layer*, que usa uma das funções `scale_colour_X`. | |
<br> | |
Tudo num ggplot é customizável, e `scale_X_X` é uma das maneiras de fazer isso. Aqui, eu vou usar o Color Brewer que vimos, usando `scale_colour_brewer()` para acessar as paletas do pacote. | |
<br> | |
```{r, eval = F} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_brewer(palette = "Blues") | |
``` | |
Hmmm...temos um erro: `Error: Continuous value supplied to discrete scale`. | |
<br> | |
Isso acontece porque temos dois tipos básicos de variável: contínua (número) e discreta (categoria). As escalas de `scale_colour_brewer()` são feitos para variáveis discretas, e `disp` é um número. | |
A função `scale_colour_distiller()` pode ser usado neste caso. | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") | |
``` | |
<br> | |
## tipo de variáveis | |
Suas variáveis podem ser quantitativas ou qualitativas. Números normalmente são variáveis contínuas, que quer dizer que podem assumir qualquer valor num conjunto de números reais. Por exemplo: | |
```{r} | |
seq(0, 1, length.out = 50) | |
``` | |
Aqui criamos 50 números entre 0 e 1. Na verdade tem uma infinidade entre 0 e 1, então podemos considerar estes números como contínuos. | |
<br> | |
Também temos valores númericos discretas: | |
```{r} | |
seq(1, 7, by = 1) | |
``` | |
Estes números podem representar categorias (com ordem ou não), e por isso variáveis assim são úteis. Um `Factor` é o tipo de variável que R cria quando tem categorias numa variável caracter. Por exemplo: | |
```{r} | |
filhos <- c("primeiro", "segundo", "terceiro", "primeiro") | |
filhos <- as.factor(filhos) | |
levels(filhos) | |
str(filhos) | |
``` | |
<br> | |
O tipo de gráfico que você pode produzir também depende do tipo da variável. Em nossos gráficos, `disp` e `mpg` são qual tipo de variável? | |
Este código vai ter pontos onde no gráfico? Por quê? | |
```{r, eval = F} | |
ggplot(mtcars, aes(x = am, y = wt)) + | |
geom_point() | |
``` | |
<br> | |
Todo tipo de gráfico diz algo diferente. | |
 | |
<br> | |
<br> | |
## legendas | |
O que usamos em `aes()` é importante, pois vai criar legenda. Por isso tinhamos duas legendas nos gráficos de cima. | |
Tem mais que um método de remover legendas, mas um jeito simples é para usar `guides()` com o estético que não queremos (aqui vou remover "size") igual `FALSE`: | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
guides(size = FALSE) | |
``` | |
Posso remover todas as legendas com: | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
theme(legend.position = "none") | |
``` | |
## themes | |
O ggplot2 tem muitos 'themes', que podem ser customizados ou usados inteiramente. Por exemplo, os gráficos que estamos criando até agora estão usando o tema default. Eu posso acessar elementos deste tema e os mudar. Todo gráfico tem muitos elementos que podem ser alterados. É muito importante consultar a documentação da função theme: [http://ggplot2.tidyverse.org/reference/theme.html](http://ggplot2.tidyverse.org/reference/theme.html) | |
Por exemplo, suponha que quero mudar o estilo do eixo x: | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
guides(size = FALSE) + | |
theme(axis.title.x = element_text(family = "Courier", | |
face = "bold", | |
colour = "blue", | |
size = 16), | |
axis.text.x = element_text(family = "Times", | |
face = "italic", | |
size = 12)) | |
``` | |
<br> | |
É a mesma coisa para o eixo y, ou para dois você usa só `axis.text`. Todas essas funções tem documentação também. Por exemplo: | |
```{r, eval = F} | |
?element_line | |
``` | |
<br> | |
Para tirar algo do gráfico, usa `element_blank()`. | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
theme(axis.title = element_blank(), | |
axis.text = element_blank(), | |
axis.ticks = element_blank(), | |
legend.position = "none") | |
``` | |
Também, o pacote tem uns temas que você pode usar com `theme_X()`: | |
### bw (Black & White): | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
theme_bw() | |
``` | |
### minimal | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
theme_minimal() | |
``` | |
### Escuro | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
scale_colour_distiller(palette = "PuOr") + | |
theme_dark() | |
``` | |
<br> | |
## Fonts | |
R usa esses fonts por default, que não é super ótimo: | |
```{r, echo = F, warning=FALSE, message=FALSE, fig.height=8} | |
fonttable <- read.table(header=TRUE, sep=",", stringsAsFactors=FALSE, | |
text=' | |
Short,Canonical | |
mono,Courier | |
sans,Helvetica | |
serif,Times | |
,AvantGarde | |
,Bookman | |
,Helvetica-Narrow | |
,NewCenturySchoolbook | |
,Palatino | |
,URWGothic | |
,URWBookman | |
,NimbusMon | |
URWHelvetica,NimbusSan | |
,NimbusSanCond | |
,CenturySch | |
,URWPalladio | |
URWTimes,NimbusRom | |
') | |
fonttable$pos <- 1:nrow(fonttable) | |
library(reshape2) | |
fonttable <- melt(fonttable, id.vars="pos", measure.vars=c("Short","Canonical"), | |
variable.name="NameType", value.name="Font") | |
# Make a table of faces. Make sure factors are ordered correctly | |
facetable <- data.frame(Face = factor(c("plain","bold","italic","bold.italic"), | |
levels = c("plain","bold","italic","bold.italic"))) | |
fullfonts <- merge(fonttable, facetable) | |
ggplot(fullfonts, aes(x=NameType, y=pos)) + | |
geom_text(aes(label=Font, family=Font, fontface=Face)) + | |
facet_wrap(~ Face, ncol=2) | |
``` | |
<br> | |
<br> | |
Se você quiser usar um font específico, pode usar o pacote `extrafont`. (Uma nota: `;` que pode ser usado no R para indicar nova linha.) | |
```{r, eval = F} | |
library(extrafont) | |
font_import("Trebuchet MS") | |
``` | |
Depois você pode usar este font (Trebuchet MS) nos gráficos. | |
<br> | |
<br> | |
## ggthemes e ggthemr | |
Tem vários pacotes que criam temas diferentes para ggplot. O `ggthemes` foi o primeiro e vou mostrar como funciona. | |
`ggthemes` pode ser instalado do CRAN (quer dizer, normalmente). | |
Com esse pacote, podemos trocar o tema inteira sem fazer muito trabalho. Ele tem temas do Economist, Google, e outros. | |
[https://github.com/jrnold/ggthemes](https://github.com/jrnold/ggthemes) | |
<br> | |
Por exemplo: | |
```{r} | |
library(ggthemes) | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
theme_hc() | |
``` | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
theme_excel() | |
``` | |
```{r} | |
ggplot(mtcars, aes(x = disp, y = mpg, colour = disp, size = disp)) + | |
geom_point() + | |
theme_fivethirtyeight() | |
``` | |
<br> | |
<br> | |
<bdi style="color:#1874CD;"> | |
Olha à base `mtcars`. Quais variáveis talvez tenham relações interessantes? Faz uns gráficos de dispersão usando as variáveis dessa base. Muda cores, fonts, e tira elementos até você está feliz com o seu gráfico. Se quiser, pode usar o ggthemes para utilizar um tema específico. | |
</bdi> | |
<br> | |
<br> | |
## Usando outros geoms | |
Os geoms que você vai usar tem algo a ver com as variáveis que vão ser no gráfico: o tipo, e a relação entre elas. | |
<br> | |
### `geom_smooth()` | |
<br> | |
Suponha que queremos ver o resultado de um modelo linear entre duas variáveis numericos. O ggplot2 tem uma base chamado `mpg`, vamos carregar. | |
Eu estou interessado na relação entre `displ` e `hwy`, e quero ver um gráfico de dispersão com uma reta no gráfico. Eu posso fazer com `geom_smooth`...mas como? | |
<br> | |
<br> | |
```{r} | |
ggplot(mpg, aes(x = displ, y = hwy)) + | |
geom_point() + | |
geom_smooth() | |
``` | |
Não vamos fazer muita da estatística neste curso, mas com `geom_smooth()` você pode usar outros métodos, como um modelo linear: | |
```{r} | |
ggplot(mpg, aes(x = displ, y = hwy)) + | |
geom_point() + | |
geom_smooth(method = "lm") | |
``` | |
Para quem não conhece muita estatística, essa linha é a linha entre as duas variáveis que tem menos distância entre ela e os pontos. | |
<bdi style="color:#1874CD"> | |
Usa `geom_smooth()`, com qualquer method que você prefere, para fazer uns gráficos das variáveis na base `mtcars`. Pode também customizar o gráfico, usando ggthemes etc. | |
</bdi> | |
<br> | |
<br> | |
## Principais gráficos | |
### Séries temporais | |
Para as séries de tempo, o ggplot tem o gráfico de linhas `geom_line()` e o `geom_path()`. As vezes você vai ter que arranjar os seus dados num formato "long" (usando `tidyr`) para conseguir fazer um gráfico assim. | |
```{r} | |
ggplot(economics, aes(x = date, y = unemploy)) + | |
geom_line(colour = "navyblue") + | |
theme_classic() + | |
theme(axis.text = element_text(family = "Times", face = "italic"), | |
axis.title = element_text(family = "Times", face = "italic")) | |
``` | |
<br> | |
Se você quiser plotar três variáveis com linhas diferentes, usa `group`: | |
```{r} | |
data("population") | |
population <- population %>% | |
filter(country %in% c("Germany", "United States of America", "Uganda", "Brazil")) | |
ggplot(population, aes(x = year, y = population, group = country)) + | |
geom_line(aes(colour = country)) + | |
theme_classic() | |
``` | |
<br> | |
### Gráficos de barra | |
Se precisarmos da distribuição de variáveis qualitativas, usem o gráfico de barras. Esse é bom para ver a quantidade em cada categoria, por exemplo. Este geom não usa o argumento `y` na `aes()`. | |
```{r} | |
ggplot(mpg, aes(x = manufacturer)) + | |
geom_bar() | |
``` | |
As barras podem ser coloridas com `colour` e `fill`: | |
```{r} | |
ggplot(mpg, aes(x = manufacturer)) + | |
geom_bar(colour = "#8B2323", fill = "#EE3B3B") + | |
theme_classic() | |
``` | |
Esse gráfico tem problemas com os nomes no eixo x. Pode resolver isso usando `coord_flip()`: | |
```{r} | |
ggplot(mpg, aes(x = manufacturer)) + | |
geom_bar(colour = "#8B2323", fill = "#EE3B3B") + | |
theme_classic() + | |
coord_flip() | |
``` | |
<br> | |
<bdi style="color:#1874CD"> | |
Vamos carregar a base `diamonds` que vem com ggplot2. Tem variáveis nela que podemos usar para fazer gráfico de barra? Faz um que você gosta. | |
</bdi> | |
<br> | |
<br> | |
### Dotplots | |
Esses gráficos de barra nós traz perto de um outro tipo de gráfico que é muito útil, o dotplot. Tem dois tipos de dotplot, um que podemos criar com `geom_dotplot()` e uma outro que criamos com `geom_point()` e `geom_segment()`. | |
Com `geom_dotplot()`, se você muda o `binwidth`, os pontos vão mudar de tamanho. | |
```{r} | |
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) + | |
geom_dotplot(binaxis = "y", | |
binwidth = 0.1, | |
stackdir = "center") | |
``` | |
Podemos usar `stat_summary()` para mostrar onde é a média ou mediana, por exemplo: | |
```{r} | |
ggplot(iris, aes(x = Species, y = Sepal.Length, fill = Species)) + | |
geom_dotplot(binaxis = "y", | |
binwidth = 0.1, | |
stackdir = "center") + | |
stat_summary(fun.y = median, geom = "point", shape = 21, | |
size = 4, color = "black", fill = "white") | |
``` | |
<bdi style="color:#1874CD>Não é *tão* claro...será que vocês podem melhorar?</bdi> | |
<br> | |
<br> | |
Para criar um *Cleveland Dot Plot*, eu vou usar um exemplo do livro do Winston Chang (que, claro, tem um pacote). | |
```{r} | |
# install.packages("gcookbook") | |
library(gcookbook) | |
``` | |
<br> | |
Este pacote tem uma base chamado "tophitters2001", que é jogadores de baseball e os pontos deles. Vamos carregar. | |
```{r} | |
data("tophitters2001") | |
head(tophitters2001) | |
``` | |
<br> | |
Vamos selecionar só as primeiras 25 linhas. Depois isso, é só criar gráfico com `geom_point()`. `y` vai ser `name` e `x` vai ser `avg`. | |
<br> | |
<br> | |
<br> | |
```{r} | |
top <- tophitters2001[1:25, ] | |
ggplot(top, aes(x = avg, y = name)) + geom_point() | |
``` | |
Este é bom, mas seria melhor se pudessemos ordenar os nomes. `ggplot()` ordena `name` alfabeticamente. (Porquê?) | |
<br> | |
A solução é transformar `name` num Factor, que é ordenado por `avg`. No R, a função para fazer isso é `reorder()`. Nós vamos reordenar `name` usando `avg`, que podemos fazer dentro do `ggplot()`: | |
```{r} | |
ggplot(top, aes(x = avg, y = reorder(name, avg))) + | |
geom_point() | |
``` | |
Uma outra coisa que ajuda com Cleveland dot plots é uma linha até o ponto, que fazemos com `geom_segment()`. Aqui, eu vou pôr antes da função `geom_point()`...por quê? | |
```{r} | |
ggplot(top, aes(x = avg, y = reorder(name, avg))) + | |
geom_point(shape = 21, fill = "white", colour = "black", size = 2) + | |
geom_segment(aes(yend = name), xend = 0, colour = "grey50") | |
``` | |
```{r} | |
ggplot(top, aes(x = avg, y = reorder(name, avg))) + | |
geom_segment(aes(yend = name), xend = 0, colour = "grey50") + | |
geom_point() | |
``` | |
<br> | |
<bdi style="color:#1874CD"> | |
Este gráfico ainda não é *fantástico*. Arruma ele para ficar mais claro e fácil ler. O gráfico dispõe sobre o que? O que são as variáveis? Pode usar `ggtitle()` e `labs()` para incluir mais informação. | |
</bdi> | |
<br> | |
<br> | |
### Boxplots, jitterplots e violinplots | |
Quando temos uma variável quantitativa e uma qualitativa, também podemos usar um gráfico de dispersão. | |
Para o banco 'diamonds', podemos medir como varia o preço , tendo em vista a qualidade da lapidação ('cut'). | |
```{r} | |
ggplot(diamonds, aes(x = cut, y = price)) + | |
geom_point() | |
``` | |
<br> | |
Porém, eles podem não ser ideais para o que queremos. Nesse caso, seria melhor utilizar um 'boxplot'. | |
```{r} | |
ggplot(diamonds, aes(x = cut, y = price)) + | |
geom_boxplot() | |
``` | |
O que o boxplot mostra? Está dizendo o que sobre a variável `cut` em termos da `price`? | |
<br> | |
A função `geom_boxplot()` também aceita parâmetros como `colour` e `fill`: | |
```{r} | |
ggplot(diamonds, aes(x = cut, y = price)) + | |
geom_boxplot(fill = "#FFEC8B", colour = "#8B5742") + | |
theme_classic() | |
``` | |
<br> | |
Também são interessantes o 'jitterplot' e o 'violinplot'. O jitterplot mostra a dispersão dentro de uma categoria. | |
```{r} | |
ggplot(diamonds, aes(x = cut, y = price)) + | |
geom_jitter() + | |
theme_bw() | |
``` | |
<br> | |
O violinplot mostra a mesma coisa: | |
```{r} | |
ggplot(diamonds, aes(x = cut, y = price)) + | |
geom_violin(fill = "hotpink", alpha = 0.35) + | |
theme_minimal() | |
``` | |
<br> | |
<bdi style="color:#1874CD">Explora a relação o tamanho e peso dos `Petals` e `Species` nas base `iris`, usando boxplots, voilin plots e jitter plots.</bdi> | |
<br> | |
### Histogramas e freqpoly | |
Quando temos apenas uma variável quantitativa, vale a pena verificar a distribuição dessa variável. Para isso, usamos histogramas e densidades. São mais detalhados que os boxplots e podem ser ideais, dependendo do caso. Por exemplo, se queremos analisar a distribuição de `carat` no dataset 'diamonds': | |
```{r} | |
ggplot(diamonds, aes(x = carat)) + | |
geom_histogram(bins = 30, fill = "#4876FF", colour = "#00008B") | |
``` | |
<br> | |
A especificação dos 'bins' (barras) é importante. Pode mostrar ou esconder aspectos importantes dos dados. | |
Por exemplo, o mesmo grafico com menos bins: | |
```{r} | |
ggplot(diamonds, aes(x = carat)) + | |
geom_histogram(bins = 5, fill = "#4876FF", colour = "#00008B") | |
``` | |
Ou mais: | |
```{r} | |
ggplot(diamonds, aes(x = carat)) + | |
geom_histogram(bins = 100, fill = "#4876FF", colour = "#00008B") | |
``` | |
É boa prática fazer gráficos assim com número de bins diferente. Dado que é tão rápido e simples mudar isso, vale a pena fazer. | |
<bdi style="color:#1874CD">Faz histogramas da variável `avg` nas base `tophitters2001`, usando `bins = 5`, `bins = 25` e `bins = 50`. Faz diferença ou não à distribuição da variável?</bdi> | |
<br> | |
<br> | |
Também é possível criar `freqpoly`, no lugar dos histogramas. | |
```{r} | |
ggplot(diamonds, aes(x = price)) + | |
geom_freqpoly(color = "black") | |
``` | |
Por que usa isso? Porque podemos mostra mais que uma variável num gráfico só: (nota o uso do `aes()` cada vez) | |
```{r} | |
ggplot(diamonds) + | |
geom_freqpoly(aes(x = depth), color = "black") + | |
geom_freqpoly(aes(x = carat), color = "firebrick") + | |
geom_freqpoly(aes(x = table), color = "blue") + | |
theme_classic() | |
``` | |
Não quer dizer que isso sempre é uma boa ideia, mas é fácil com `geom_freqpoly`, enquanto não era possível com `geom_histogram`. | |
<br> | |
Por fim, podemos adicionar a densidade ao histograma. A sintaxe é um pouco estranha com `y`: | |
```{r} | |
ggplot(diamonds, aes(x = price)) + | |
geom_histogram(bins = 30, fill = "#4876FF", | |
colour = "#00008B", aes(y = ..density..)) + | |
geom_density(size = 1) | |
``` | |
<br> | |
`geom_density()` é útil para vizualizar variáveis: | |
```{r} | |
ggplot(diamonds, aes(x = carat)) + | |
geom_density(fill = "#4876FF", colour = "#00008B") | |
``` | |
<bdi style="color:#1874CD">Cria gráficos de densidades das primeiras quatro variáveis na base `airquality`. São semelhantes? Ou não?</bdi> | |
<br> | |
<br> | |
## Plotando funções | |
<br> | |
Também podemos mostrar só funções com `ggplot()` usando `stat_function()`: | |
```{r} | |
ggplot(data.frame(x = c(0, 10)), aes(x)) + | |
stat_function(fun = sin, colour = "blue") + | |
stat_function(fun = cos, colour = "red") + | |
theme_minimal() | |
``` | |
Ou usando as funções que criam densidades (`dnorm` e `dt`, por exemplo): | |
```{r} | |
ggplot(data_frame(x = c(-4, 4)), aes(x = x)) + | |
stat_function(fun = dnorm) + | |
theme_classic() | |
``` | |
```{r} | |
ggplot(data.frame(x = c(-4, 4)), aes(x = x)) + | |
stat_function(fun = dt, args = list(df = Inf), color = "black") + | |
stat_function(fun = dt, args = list(df = 8), color = "darkgreen") + | |
stat_function(fun = dt, args = list(df = 5), color = "red") + | |
stat_function(fun = dt, args = list(df = 2), color = "yellow") + | |
theme_minimal() | |
``` | |
Ou suas próprias funções: | |
```{r} | |
func <- function(x){ | |
x^2 + x + 20 | |
} | |
func_2 <- function(x) {-1 * x + 10} | |
func_3 <- function(x) 3 * x + 2 | |
ggplot(data.frame(x = c(-10, 10)), aes(x)) + | |
stat_function(fun = func, color = "darkorange") + | |
stat_function(fun = func_2, color = "navy") + | |
stat_function(fun = func_3, color = "firebrick") + | |
theme_bw() | |
``` | |
<br> | |
<bdi style="color:#1874CD">Estou interessado em ver umas distribuições beta, feito com `dbeta`, com valores diferentes dos parâmetros `shape1` e `shape2`. Para quem não conhece a distrbuição beta, o `x` tem que ser entre 0 e 1. Este exemplo usa `shape1 = 0.5` e `shape2 = 0.5`:</bdi> | |
```{r, echo = F} | |
ggplot(data.frame(x = c(0, 1)), aes(x = x)) + | |
stat_function(fun = dbeta, args = list(shape1 = .5, shape2 = .5), color = "goldenrod1") + | |
theme_minimal() | |
``` | |
<br> | |
<br> | |
## Facets | |
Na outra aula vimos o `group_by()`. As funções de "facet", `facet_grid()` e `facet_wrap()` funcionam de uma lógica semelhante. `facet_grid()` faz um grid, e `facet_wrap()` cria algo semelhante, mas não necessariamente num grid. A sintaxe é quase igual, só que `facet_wrap()` não aceita `.` na formula que especifica como fazer o agrupamento. (`.` quer dizer todas as variáveis mencionadas em `aes()`). | |
<br> | |
Um exemplo, e essa vez eu vou criar um objeto do gráfico básico. | |
```{r} | |
graph <- ggplot(mpg, aes(displ, cty)) + | |
geom_point() | |
``` | |
```{r} | |
graph + facet_grid(. ~ cyl) | |
graph + facet_grid(drv ~ .) | |
graph + facet_grid(drv ~ cyl) | |
``` | |
<br> | |
Um exemplo de `facet_wrap()`: | |
```{r} | |
ggplot(mpg, aes(x = displ, y = hwy)) + | |
geom_point() + | |
facet_wrap(~ class) | |
``` | |
<br> | |
Exatamente como o `group_by()`, é fácil ver as possibilidades com os facets. Por exemplo, eu posso rodar cinco modelos e mostrar num gráfico só (`modelr` vem com o tidyverse): | |
```{r} | |
library(modelr) | |
mod1 <- lm(mpg ~ poly(wt, 1), data = mtcars) # linear | |
mod2 <- lm(mpg ~ poly(wt, 2), data = mtcars) # quadratico | |
mod3 <- lm(mpg ~ poly(wt, 3), data = mtcars) # cubo | |
mod4 <- lm(mpg ~ poly(wt, 4), data = mtcars) # quarto grau | |
mod5 <- lm(mpg ~ poly(wt, 5), data = mtcars) # quinto | |
grid <- mtcars %>% | |
data_grid(wt) %>% | |
gather_predictions(mod1, mod2, mod3, mod4, mod5, | |
.pred = "mpg") | |
ggplot(mtcars, aes(wt, mpg)) + | |
geom_point() + | |
geom_line(data = grid, colour = "red") + | |
facet_wrap(~ model) | |
``` | |
Este tipo de modelagem é um pouco fora do escopo do curso, mas como podem ver, não é difícil fazer isso em ggplot2. | |
<br> | |
<bdi style="color:#1874CD">Da base `iris`, cria um gráfico que usa um facet para explorar com uma variável muda nos níveis de uma outra que tem categorias.</bdi> | |
<br> | |
## Mostrando todos os dados no fundo | |
Facets são ótimos, mas perdemos a distribuição total. Por exemplo: | |
```{r} | |
ggplot(iris, aes(x = Sepal.Width)) + | |
geom_histogram() | |
``` | |
```{r} | |
ggplot(iris, aes(x = Sepal.Width)) + | |
geom_histogram() + | |
facet_wrap(~ Species) | |
``` | |
Podemos 'melhorar' isso com gráficos "stacked" (realmente não gosto desses gráficos): | |
```{r} | |
ggplot(iris, aes(x = Sepal.Width, fill = Species)) + | |
geom_histogram() | |
``` | |
<br> | |
Ou podemos plotar o gráfico primeiro no fundo dos facets. Esse é um "truque" que foi postado na internet, e eu acho ótimo. O truque involve usar dois dataframes: | |
```{r} | |
df <- iris # base inteira | |
df_2 <- df[, -5] # base sem a variável de facet | |
ggplot(df, aes(x = Sepal.Width, fill = Species)) + | |
geom_histogram(data = df_2, fill = "grey", alpha = .5) + # fundo | |
geom_histogram(colour = "black") + | |
facet_wrap(~ Species) + | |
guides(fill = FALSE) + # tirar legenda | |
theme_bw() | |
``` | |
É importante lembrar que você sempre pode usar outras bases com as funções `geom_X()`, não tem que ser a base original. | |
## Usando mais que uma base | |
Na função `ggplot()`, o primeiro argumento é a base. Podemos usar outras bases nos outros layers. As vezes isso é necessário, se você quiser alterar cores ou fills que já são ligados a umas variáveis. | |
```{r} | |
graf <- ggplot(diamonds, aes(x = carat, y = price)) + | |
geom_point(colour = "navyblue", alpha = 0.7) + | |
theme_classic() | |
graf | |
``` | |
```{r} | |
diamonds2 <- diamonds %>% | |
mutate(Mean = mean(carat)) %>% | |
distinct(Mean, .keep_all = T) | |
graf + | |
geom_point(data = diamonds2, aes(x = Mean, y = price), colour = "red") | |
``` | |
## `annotate()` | |
A função `annotate()` nós deixa criar anotações em nossos plots. (vai ter que adivinhar um pouco em relação a posição) | |
```{r} | |
graf + | |
geom_point(data = diamonds2, aes(x = Mean, y = price), colour = "red") + | |
annotate(geom = "segment", x = 0.85, xend = 1.5, y = 400, | |
yend = 400, colour = "red") + | |
annotate(geom = "label", x = 1.5, y = 400, label = "Important Thing", | |
size = 3, colour = "red") | |
``` | |
Pode fazer anotações de formulas ou caracteres matemáticas com `expression()`. | |
```{r} | |
graf + | |
geom_point(data = diamonds2, aes(x = Mean, y = price), colour = "red") + | |
annotate(geom = "segment", x = 0.85, xend = 1.5, y = 400, | |
yend = 400, colour = "red") + | |
annotate(geom = "text", x = 1.65, y = 400, label = "delta", | |
size = 6, colour = "red", parse = TRUE) | |
``` | |
<br> | |
<br> | |
<br> | |
<br> | |
## Exercícios | |
<bdi style="color:#1874CD"> | |
1 - Escolha 7 países da base `population` que te interesse e faz uma séries de tempo usando `geom_line()` e `group`. Faz anotação dos nomes dos países nas linhas deles. Qual fica melhor, `text` ou `label`? | |
2 - Cria um gráfico de facet com `facet_wrap()` e/ou `facet_grid()` para ver como `price` e `carat` variam com `color` da base `diamonds`. | |
3 - Da base `chickwts`, eu quero ver densidades da variável `weight` num facet feito por `feed`. Faz o gráfico fácil ler e entender. Faz o mesmo com histograma, usando todos os dados no fundo. Qual você acha melhor? | |
4 - Dado que `weights` é uma variável númerico, e `feed` é categorica, quais tipos de plots seriam bons para mostrar a relação entre essas variáveis? | |
5 - Usa `stat_function` com `args = list()` para criar um gráfico de cinco distribuições normais, cada um com uma média diferente e desvio padrão diferente. Usa cores diferentes para distinguir entre elas. | |
</bdi> | |
<br> | |
<br> | |
<br> | |
## extensões ao ggplot2 | |
Uma das coisas melhores sobr o ggplot2 é o número de pacotes construídos em cima dele. Já vimos uma com `ggthemes`. | |
[https://www.ggplot2-exts.org/ggseas.html](https://www.ggplot2-exts.org/ggseas.html) | |
<br> | |
Tem tanto que tem o próprio website, e que até tem extensões meio ridículas. | |
[https://cran.r-project.org/web/packages/emojifont/vignettes/emojifont.html](https://cran.r-project.org/web/packages/emojifont/vignettes/emojifont.html) | |
<br> | |
# Gráficos interativos | |
Uma área interessante que está em muito desenvolvimento é gráficos interativos. Para fazer um gráfico interativo, é necessário usar um browser, ou o browser do RStudio, ou um como Chrome ou Firefox. | |
<br> | |
Tem muitos pacotes que exploram essa área, construído no ggplot2 ou na base. Uns são simples, outros são muito complexos. Eu vou mostrar dois aqui, o `ggiraph` (uma brincadeira com "giraffe" supostadamente...) e o `plotly`. Plotly é um website que te ajuda faz gráficos interativos dos seus dados (https://plot.ly/). O pacote é poderoso, mas a documentação não é tão bom. `ggiraph` é muito simples. A versão interativo do ggplot2 é `ggvis`, que está em desenvolvimento. | |
<br> | |
## `ggiraph` | |
O `ggiraph` funciona com uma nova linha de geoms: `geom_X_interactive()`, onde `X` é `point`, `line` etc. | |
```{r} | |
library(ggiraph) | |
data("iris") | |
iris$clickjs = paste0("alert(\"", | |
iris$Species, "\")" ) | |
# plots | |
gg_point = ggplot(iris, aes(x = Sepal.Length, y = Petal.Width, | |
color = Species, tooltip = Species, | |
onclick = clickjs) ) + | |
geom_point_interactive() | |
ggiraph(code = {print(gg_point)}) | |
``` | |
Como podem ver, esse só adiciona `tooltip` (o valor que é mostrado quando você para em cima do ponto), o que acontece quando clica e um novo geom. | |
<bdi style="color:#1874CD">Escolha um dos gráficos que fizemos mais cedo e adiciona os elementos necessários para fazer um gráfico interativo com `ggiraph`.</bdi> | |
<br> | |
<br> | |
## `plotly` | |
**Aviso: todos os gráficos interativos do plotly são mais pesados na memória do R.** | |
```{r, eval =F} | |
install.packages("plotly") | |
library(plotly) | |
``` | |
```{r, echo = F} | |
library(plotly) | |
``` | |
<br> | |
A função principal do `plotly`, em relação ao `ggplot2`, é `ggplotly()`. Essa transforma um gráfico normal do `ggplot()` num gráfico interativo. Para usar, precisamos salvar o gráfico como um objeto. Um exemplo de um gráfico que fizemos mais cedo (não mostro o gráfico aqui pois é pesado): | |
```{r, eval = F} | |
plot1 <- ggplot(mpg, aes(x = displ, y = hwy)) + | |
geom_point() + | |
geom_smooth(method = "lm") | |
(gg <- ggplotly(plot1)) | |
``` | |
<br> | |
Plotly é semelhante ao ggiraph, mas tem umas coisas extras. Por exemplo, este exemplo da documentação deles: | |
```{r, eval = F} | |
plot_ly(z = volcano, type = "surface") | |
``` | |
Também eu vi um helicóptero 3D feito assim no R usando plotly. A documentação não ajuda muito, mas dá para fazer. | |
## Imagens no fundo | |
Uma coisa que eu acho impressionante num gráfico é uma imagem `phylopic` a um gráfico. | |
```{r, eval = F} | |
install.packages("rphylopic", "OutbreakTools") | |
``` | |
```{r, echo = F} | |
# devtools::install_github("sckott/rphylopic") | |
library(rphylopic) | |
library(OutbreakTools) | |
``` | |
Primeiro, vamos simular dados num dataframe: | |
```{r} | |
species <- data_frame(animals = rep(c("tarantula", "lizard", "moth"), | |
each = 30), | |
days = c(1:30, 1:30, 1:30), | |
count = c(rnorm(30, mean = 15, sd = 2), | |
rnorm(30, 9, 2), | |
rnorm(30, 30, 2))) %>% | |
mutate(count = ceiling(count)) | |
``` | |
Depois, vamos ao website desses imagens para achar o código do animal.[http://phylopic.org/image/browse/](http://phylopic.org/image/browse/) | |
```{r, message=FALSE, warning = FALSE} | |
tarantula <- rphylopic::image_data("d780fdc0-311f-4bc5-b4fc-1a45f4206d27", | |
size = "512")[[1]] | |
lizard <- rphylopic::image_data("9cae2028-126b-416f-9094-250782c5bc22", | |
size = "512")[[1]] | |
moth <- rphylopic::image_data("8229756b-82c3-4a9f-a1c6-e88f958e623e", | |
size = "512")[[1]] | |
``` | |
<br> | |
Neste gráfico, nós vamos colocar três gráficos ao lado de um a outro, usando a função `grid.arrange()` do pacote `gridExtra` (o pacote `cowplot` também é bom pra isso, talvez melhor até). Construimos três gráficos, salvados como objetos, para usar nessa função. | |
```{r} | |
# install.packages("gridExtra") | |
library(gridExtra) | |
plot_1 <- ggplot(species[1:30,], aes(x = days, y = count)) + | |
add_phylopic(tarantula, alpha = 0.5) + | |
theme_minimal() + | |
geom_point() | |
plot_2 <- ggplot(species[31:60,], aes(x = days, y = count)) + | |
add_phylopic(lizard, color = "palegreen4", alpha = 0.5) + | |
theme_minimal() + | |
geom_point(colour = "palegreen4") | |
plot_3 <- ggplot(species[61:90,], aes(x = days, y = count)) + | |
add_phylopic(moth, color = "firebrick", alpha = 0.5) + | |
theme_minimal() + | |
geom_point(colour = "firebrick") | |
grid.arrange(plot_1, plot_2, plot_3, ncol=3) | |
``` | |
Pode também inserir imagem usando `readX`, onde X é o formato, para plots usando base R, por exemplo `readPNG("image.png")`. | |
<br> | |
<bdi style="color:#1874CD"> | |
1 - Faz um destes gráficos dos animais interativo, usando ggiraph ou plotly. | |
2 - Escolha um dos gráficos que você fez mais cedo e insera um imagem de um animal no fundo e o faz interativo. | |
</bdi> | |
<br> | |
## gifs | |
Um outro bom é `gganimate` que nós deixa cria animações em nossos gráficos. A chave com essas é que temos uma coluna no nosso dataframe que usamos para `frame`, ou cada passo na sequencia da animação. (Também tem pacotes para gifs etc.) | |
```{r, eval = F} | |
# install.packages(gapminder, gganimate) | |
library(gapminder) | |
library(gganimate) | |
data("gapminder") | |
plot3 <- ggplot(gapminder, aes(x = gdpPercap, y = lifeExp, | |
size = pop, color = continent, | |
frame = year)) + | |
geom_point() + | |
scale_x_log10() | |
gganimate(plot3) | |
``` | |
Animações como essa são úteis quando toda a informação que você quer mostrar não cabe num gráfico. Daí você pode usar `frame` para passar por estágios numa variável (como no tempo, por exemplo). | |
<br> | |
<bdi style="color:#1874CD"> | |
Hora do Projeto 1!!! | |
</bdi> | |
# Mapas | |
Tem dois jeitos de fazer mapas no R: acessar um software que cria a mapa para você (e que é mais ou menos pronto), ou criar a mapa usando "shapefiles". O primeiro é mais fácil, mas é limitado para customizar ou usar com dados seus, e o segundo é bem mais complexo por causa dos shapefiles, que normalmente são listas grandes. | |
Um exemplo bom que foi feito no R com `ggiraph`: | |
[http://www.swissinfo.ch/eng/migration-series_europe-s-immigration-balance-sheet/42495760](http://www.swissinfo.ch/eng/migration-series_europe-s-immigration-balance-sheet/42495760) | |
<br> | |
## `ggmap` | |
O objetivo do pacote `ggmap` é obter dados de mapas de serviços populares na Internet como o Google Maps e os plotar usando a sintaxe do `ggplot2`. | |
Contudo, ultimamente a API do Google Maps está muito instável, o que faz com que muitas funções funcionem hora sim hora não. Por esse motivo, não é recomendável usar algumas das funções do `ggmap`, como `qmap` e `get_googlemap`, para projetos sérios. Felizmente, ainda existem outras funções do pacote que funcionam bem. | |
```{r, message=FALSE, warning=FALSE, eval = FALSE} | |
# Pode nao funcionar: | |
qmap(location = "universidade de sao paulo", maptype = "toner", | |
source = "stamen", | |
zoom = 14) | |
``` | |
<br> | |
```{r} | |
# Pode nao funcionar | |
get_googlemap("aracaju", zoom = 12, maptype = "satellite") %>% | |
ggmap() | |
``` | |
<br> | |
Uma das funções que ainda pode ser usada (com certa cautela) é a `geocode`, que extrai as coordenadas geográficas do endereço de input. | |
```{r, message=FALSE} | |
enderecos <- c("Parque do Ibirapuera Sao Paulo", | |
"Avenida Paulista 2202 Sao Paulo", | |
"Aeroporto Internacional de Guarulhos") | |
coord <- geocode(enderecos) | |
``` | |
Essa função pode ser usada em combinação com a `qmplot` para plotar um mapa: | |
```{r} | |
qmplot(lon, lat, data = coord, color = "red") | |
``` | |
A `qmap()` e `qmplot()` são wrappers da função `ggmap()` e da `get_map()`, funções que tem mais opções e são mais poderosos. Frequentemente, vai precisar das coordinatas geográficas. Um site útil é esse: | |
[http://www.gps-coordinates.net/](http://www.gps-coordinates.net/) | |
<br> | |
Também é possível fazer gráficos mais complexos com a função `qmplot`: | |
`qmplot()` é muito útil: | |
```{r, message=FALSE, warning=FALSE} | |
violent_crimes <- crime %>% | |
filter(offense != "auto theft", | |
offense != "theft", | |
offense != "burglary", | |
lon >= -95.39681 & lon <= -95.34188, | |
lat >= 29.73631 & lat <= 29.78400) %>% | |
mutate(offense = factor(offense, | |
levels = c("robbery", | |
"aggravated assault", | |
"rape", | |
"murder"))) | |
qmplot(lon, lat, data = violent_crimes, | |
maptype = "toner-background", | |
color = offense) | |
``` | |
<bdi style="color:#1874CD">Aqui eu usei crimes violentas. As crimes não violentas mostram padrões semelhantes?</bdi> | |
<br> | |
<br> | |
Com `ggmap()`, podemos usar `left`, `bottom`, `right`, `top` para criar as margens (latitude e longitude) do plot. A `get_map()` tem alternativas, como `get_stamenmap()`, que cria mapa de uma séries de imagens: | |
```{r, message=FALSE, warning=FALSE} | |
sa <- c(left = -90, bottom = -40, right = 0, top = 10) | |
map <- get_stamenmap(sa, zoom = 5, maptype = "toner-lite") | |
ggmap(map) | |
``` | |
<br> | |
E podemos plotar rotas: | |
```{r, message=FALSE, warning=FALSE, eval = FALSE} | |
viagem <- route(from = "santos, sao paulo", | |
to = "campinas, sao paulo", | |
mode = "driving") | |
# pode nao funcionar | |
qmap("sao paulo", zoom = 8) + | |
geom_path( | |
aes(x = startLon, y = startLat), colour = "blue", | |
size = 1.5, alpha = .5, | |
data = viagem, lineend = "round") | |
``` | |
<br> | |
<br> | |
`ggmap` também tem outras possibilidades: [https://github.com/dkahle/ggmap](https://github.com/dkahle/ggmap). | |
<bdi style="color:#1874CD"> | |
Hora do Projeto 2!!! | |
</bdi> | |
<br> | |
<br> | |
<bdi style="color:#1874CD"> | |
Hora do projeto! Vamos plotar 5000 escolas da rede municipal de São Paulo! | |
</bdi> | |
## leaflet | |
E um outro pacote muito bom é `leaflet` [https://rstudio.github.io/leaflet/](https://rstudio.github.io/leaflet/): | |
```{r} | |
# install.packages("leaflet") | |
library(leaflet) | |
leaflet() %>% | |
addTiles() %>% | |
addMarkers(lng = -46.65903220000001, lat=-23.5588389, | |
popup = "Tamo aqui!") | |
``` | |
`ggmap` tem dados dos estados dos EUA e das condades. `map_data("state")` vai te dar uma dataframe das coordinatos dos todos os estados, por exemplo. | |
<bdi style="color:#1874CD">Hora do Projeto 3!!!</bdi> | |
<br> | |
## sf e geom_sf | |
Um recurso recente e muito útil para construir mapas de áreas é o combo do pacote `sf` com a função `geom_sf()`. | |
O workflow para construir um mapa usando esse combo consiste em importar um arquivo de shapefiles com a função `sf::st_read()`, que já criará um objeto no formato exigido pela `geom_sf()`. | |
```{r} | |
# o pacote sf possui alguns arquivos internos de shapefiles | |
# o arquivo nc.shp traz o shapefile dos distritos do | |
# estado de North Caroline | |
nc <- sf::st_read(system.file("shape/nc.shp", package = "sf"), quiet = TRUE) | |
class(nc) | |
``` | |
Plotar um objeto da classe `nf` é muito simples: | |
```{r} | |
ggplot(nc) + | |
geom_sf() | |
``` | |
A sintaxe funciona da mesma maneira que no `ggplot2`, ou seja, você pode atribuir variáveis do objeto a elementos do gráfico: | |
```{r} | |
ggplot(nc) + | |
geom_sf(aes(fill = AREA)) + | |
scale_fill_distiller(palette = "YlOrRd", direction = 1) | |
``` | |
<br> | |
Tem que usar "shapefiles", que pode pegar de [http://www.gadm.org/country](http://www.gadm.org/country). Dado que é avançado, e vai mudar em breve para um sistema mais fácil, vu deixar fora da aula. | |
<br> | |
<bdi style="color:#1874CD">Hora do Projeto 4, 5 e 6!!!</bdi> | |
<br> | |
# Sunburst | |
Existem dezenas ou até mesmo centenas de pacotes criados para fazer gráficos específicos, como treemaps, sankey plots, circular plots, grafos, etc. Daria para fazer um curso só disso. | |
Um que eu especialmente gosto bastante é o gráfico **Sunburst**, que é excelente para visualizar dados com estruturas hierárquicas. Gráficos sunburst podem ser feitos com o pacote `sunburstR`: [https://github.com/timelyportfolio/sunburstR](https://github.com/timelyportfolio/sunburstR) | |
```{r} | |
# devtools::install_github("timelyportfolio/sunburstR") | |
library(sunburstR) | |
# importar dados fornecidos pelo pacote | |
sequences <- read.csv( | |
system.file("examples/visit-sequences.csv",package="sunburstR") | |
,header = FALSE | |
,stringsAsFactors = FALSE | |
)[1:200,] | |
head(sequences) | |
``` | |
```{r} | |
sunburst(sequences) | |
``` | |
<bdi style="color:#1874CD">Hora do Projeto 7!!!</bdi> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
install.packages(c("RColorBrewer", "gcookbook", "modelr", | |
"ggiraph", "plotly", "rphylopic", "OutbreakTools", | |
"gridExtra", "gapminder", "leaflet", "devtools", "sf")) | |
install.packages("sf") | |
install.packages("OutbreakTools") | |
devtools::install_github("dgrtwo/gganimate") | |
devtools::install_github("dkahle/ggmap") | |
devtools::install_github("timelyportfolio/sunburstR") | |
devtools::install_github("sckott/rphylopic") | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(tidyverse) | |
library(sf) | |
library(leaflet) | |
library(jsonlite) | |
library(ggmap) | |
library(readxl) | |
library(janitor) | |
library(rvest) | |
library(gganimate) | |
library(sunburstR) | |
# Projeto 01: Destacando um estado por vez em um gráfico de série temporal com gganimate ---- | |
# Descrição do projeto: plotar a evolução temporal da taxa de homicídio dos estados BRs... | |
# e criar um gif destacando um estado por vez | |
# fonte dos dados: | |
url <- "https://pt.wikipedia.org/wiki/Lista_de_unidades_federativas_do_Brasil_por_taxa_de_homic%C3%ADdios" | |
# usar funcao do rvest para ler codigo fonte | |
url <- read_html(url) | |
# extrair tabelas da pagina | |
tabs <- url %>% | |
html_table(fill = TRUE) | |
# vamos ver se o codigo pegou a primeira tabela acertadamente | |
sapply(tabs, class) | |
tabs[[1]] %>% head() | |
# funcionou direitinho. vamos entao salvar em uma variavel e fazer algumas limpezas | |
# como ficaria um grafico inicial? usar geom_line() e mapear o uf à cor das linhas | |
# Como podemos fazer para destacar de uma maneira melhor um uf? | |
destaque <- "Sergipe" | |
# Projeto 02: Plotando escolas com ggmap ---- | |
# Descrição do projeto: Existe um dataset fornecido com as escolas municipais de SP | |
# Vamos plotá-las em um mapa usando o ggmap. | |
# dados de escolas: | |
# http://dados.prefeitura.sp.gov.br/dataset/cadastro-de-escolas-municipais-conveniadas-e-privadas/resource/dfa2e046-b975-4ff5-983f-dacfd8cb06b2 | |
# Deem uma olhada no menu API de dados e vejam uma url para fazer requisicao para... | |
# baixar os dados | |
# baixando dados de 5000 escolas: | |
limit = 8000 | |
url <- paste0( | |
"http://dados.prefeitura.sp.gov.br/api/action/datastore_search?resource_id=dfa2e046-b975-4ff5-983f-dacfd8cb06b2", | |
"&limit=", limit) | |
# ler os dados em formato json | |
json_escolas <- url %>% fromJSON() | |
# olhando a estrutura dos dados | |
View(json_escolas) | |
# estamos interessados no dataframe presente em records | |
df_escolas <- json_escolas$result$records | |
glimpse(df_escolas) | |
df_escolas %>% | |
select(LATITUDE, LONGITUDE) %>% | |
glimpse() | |
# existe um problema com as colunas de latitude e longitude. | |
# alguem sabe qual é? | |
inserir_decimal <- function(x){ | |
x <- as.character(x) | |
posicao_fim_inteiro <- ifelse(str_detect(x, "-"), 3, 2) | |
x <- paste0( | |
str_sub(x, 1, posicao_fim_inteiro), | |
".", | |
str_sub(x, posicao_fim_inteiro + 1, str_length(x)) | |
) | |
# recolocar traco caso ele existia antes | |
# retornar resultado | |
as.numeric(x) | |
} | |
# exemplo de uso | |
df_escolas$LATITUDE[1:3] | |
df_escolas$LATITUDE[1:3] %>% inserir_decimal() | |
c(-2344, 2344) %>% inserir_decimal() | |
# criar novo dataframe de uso | |
# selecionar colunas importantes | |
df_escolas_red <- df_escolas %>% | |
# selecionar colunas importantes | |
select(NOMESC, ENDERECO, LAT = LATITUDE, LON = LONGITUDE, SUBPREF, DTURNOS, | |
T2D3D) %>% | |
# criar variavel para identificar se escola tem turno noturno | |
mutate(TEM_NOTURNO = if_else(str_detect(DTURNOS, "N") | DTURNOS == "INTEGR", | |
"S", "N")) %>% | |
# usar funcao criada acima simultaneamente nas colunas LAT e LON | |
mutate_at(vars(LAT, LON), inserir_decimal) %>% | |
# filtrar fora casos em que houve erro na conversao | |
filter_at(vars(LAT, LON), any_vars(!is.na(.))) %>% | |
# remover escolas fora da grande sp (sem subprefeitura) | |
filter(SUBPREF != "") | |
# o dataset esta pronto para ser usado com o ggmap | |
centro_sp <- c(lon = mean(df_escolas_red$LON), lat = mean(df_escolas_red$LAT)) | |
map <- get_googlemap(center = centro_sp) | |
qmplot(LON, LAT, data = df_escolas_red, color = TEM_NOTURNO) | |
# deu bug na legenda das cores! vamos tentar refazer o grafico com outra funcao | |
zoom_sp <- calc_zoom(LON, LAT, data = df_escolas_red) | |
zoom_sp | |
map <- get_map(location = centro_sp, zoom = zoom_sp, maptype = "toner-lite") | |
ggmap(map) + | |
geom_point(data = df_escolas_red, aes(x = LON, y = LAT, color = TEM_NOTURNO)) + | |
facet_wrap(~ TEM_NOTURNO) | |
# aparentemente a latitude e longitude dos pontos nao varia conforme o tipo da escola | |
# sera mesmo? | |
df_escolas_red %>% | |
select(TEM_NOTURNO, LAT, LON) %>% | |
gather(COORD, VALOR, -1) %>% | |
ggplot(aes(x = VALOR, fill = TEM_NOTURNO)) + | |
geom_density( alpha = 0.3) + | |
facet_wrap(~ COORD, ncol = 1, scales = "free_x") | |
# O proximo projeto sera replicar esse grafo com o leaflet | |
# Projeto 03 : Refazer mapa das escolas com leaflet ---- | |
# criar amostra menor pq o leaflet eh pesado | |
amostra <- df_escolas_red %>% | |
group_by(TEM_NOTURNO) %>% | |
sample_n(500) | |
# criar funcao para montar popup | |
# montar_popup <- function(nome_escola, subpref){ | |
# x <- paste0( | |
# "Nome da escola: ", nome_escola, "<br>", | |
# "Subprefeitura: ", subpref, "<br>" | |
# ) | |
# x | |
# } | |
df_noturno <- amostra %>% filter(TEM_NOTURNO == "S") | |
df_sem_noturno <- amostra %>% filter(TEM_NOTURNO == "N") | |
leaflet() %>% | |
addTiles() %>% | |
addProviderTiles("OpenStreetMap.BlackAndWhite") %>% | |
addCircleMarkers( | |
data = df_noturno, | |
opacity = 1.5, | |
lng = ~LON, lat = ~LAT, | |
color = "blue", | |
popup = ~NOMESC, | |
group = "Com noturno" | |
) %>% | |
addCircleMarkers( | |
data = df_sem_noturno, | |
opacity = 1.5, | |
lng = ~LON, lat = ~LAT, | |
color = "red", | |
#popup = montar_popup(df_sem_noturno$NOMESC, df_sem_noturno$SUBPREF), | |
group = "Sem noturno" | |
) %>% | |
addLayersControl( | |
overlayGroups = c("Com noturno", "Sem noturno"), | |
options = layersControlOptions(collapsed = FALSE), | |
position = "bottomright" | |
) %>% | |
addLegend(colors = c("blue", "red"), labels = c("Com noturno", "Sem noturno")) | |
# Projeto 04: mapas brasileiros com o pacote sf ---- | |
# Etapas do projeto: | |
# 01 - Baixar shapefiles de estados e municipios brasileiros do ftp do ibge e... | |
# extrair arquivos | |
link <- "ftp://geoftp.ibge.gov.br/organizacao_do_territorio/malhas_territoriais/malhas_municipais/municipio_2016/Brasil/BR/" | |
# 02 - Importar arquivos de shapefile com a funcao sf::st_read() | |
# 03 - Criar mapa simples, colorindo os estados de acordo com a regiao geografica... | |
# com a funcao geom_sf | |
# criar funcao para limpar a aparencia do mapa | |
tema_puro <- function(){ | |
theme( | |
panel.background = element_blank(), | |
#panel.grid.major = element_blank(), | |
panel.grid.major = element_line(color = "transparent"), | |
axis.text = element_blank(), | |
axis.ticks = element_blank() | |
) | |
} | |
# refazer mapa com novo tema | |
# Projeto 05: Construir um mapa de municipios coloridos por PIB ---- | |
# 01) Baixar shapefiles de municipios e descompactar o arquivo | |
link <- "ftp://geoftp.ibge.gov.br/organizacao_do_territorio/malhas_territoriais/malhas_municipais/municipio_2016/Brasil/BR/" | |
# 02) Baixar dados de PIB por municipio e descompactar o arquivo | |
link <- "ftp://ftp.ibge.gov.br/Pib_Municipios/2015/base/" | |
# 03) Criar um novo dataframe a partir da base do PIB selecionando apenas ... | |
# algumas colunas e criando uma coluna de faixa do PIB | |
# P.S.: Olhe a distribuicao do PIB dos municipios por meio de um histograma | |
# 04) Juntar o dataframe criado em 03) com o de shapefile em um so | |
# 05) Fazer grafico, colorindo os municipios de acordo com a faixa do pib | |
# Dica: Use scale_fill_distiller para definir um palette bonito para o grafico | |
# Dica2: Use a funcao tema_puro para dar uma limpada da aparencia do grafico | |
# Dica3: Salve o grafico numa variavel chamada p e depois use ggsave() para salvar... | |
# em um arquivo local | |
# 06) Faça um mapa apenas com os municipios de um determinado estado | |
# Acrescente o recurso de adicionar um geom_text no mapa indicando o nome dos... | |
# municipios | |
# Dica: voce vai precisar usar a funcao st_centroid para extrair as coordenadas... | |
# centrais dos municipios | |
# Projeto 06: Combinando gganimate com geom_sf ---- | |
# Descrição do projeto: Ainda usando os dados de homicidio, vamos fazer um gif | |
# de um mapa mostrando as taxas de homicidio dos estados com variações anuais | |
# Exemplo de um mapa estatico: | |
# https://github.com/dpseidel/tidytuesday/blob/master/TidyWork/Week1.Rmd | |
library(tidyverse) | |
library(rvest) | |
library(gganimate) | |
library(sf) | |
library(animation) | |
# 01) Obtenha dos dados de homicidio (pode copiar e colar do outro projeto) | |
# 02) Importe a base de shapefiles | |
# 03) Essa é com vocês: faça um mapa mostrando a taxa de homicidio nos UFs | |
# no ano mais recento do dataset. | |
# 04) Essa é comigo: Use o aes frame e a funcao gganimate para plotar um gif mostrando | |
# um mapa por ano | |
# Projeto 07: Mapeando um orçamento pessoal de despesas com Sunburst | |
# 01) Crie o dataframe abaixo: | |
orcamento_pessoal <- tribble( | |
~nivel1, ~nivel2, ~nivel3, ~valor, | |
"Moradia", "Aluguel", NA, 1300, | |
"Moradia", "Condominio", NA, NA, | |
"Mercado", "Alimentação", "Carnes", 150, | |
"Mercado", "Alimentação", "Vegetais", 50, | |
"Mercado", "Mat. de limpeza e higiene", NA, 100, | |
"Transp", "Carro", NA, 400, | |
"Transp", "Publico", "Onibus", 120, | |
"Transp", "Publico", "Metrô", 50, | |
"Contas", "Energia", NA, 130, | |
"Contas", "Agua", NA, 60, | |
"Contas", "Netflix", NA, 27.90, | |
"Contas", "Internet", NA, 80, | |
"Lazer", "Restaurantes", NA, 350, | |
"Lazer", "Cultura", "Cinema", 100, | |
"Lazer", "Cultura", "Teatro", 50, | |
"Lazer", "Cultura", "Livros", 90 | |
) | |
# 02) Observe a estrutura, o formato do dataset de exemplo do sunburst. | |
# Como o sunburst reconhece uma estrutura hierarquica? | |
# Que tipo de input preciso passar para a funcão? | |
# Crie um novo dataframe com essa estrutura | |
# orcamento_pessoal_sb = | |
# 03) Plote o sunburst com o dataframe construido | |
# 04) Para remover hierarquias nao usadas (NA), substitua todos os NAs | |
# nas colunas de classe character por um string vazio | |
# 05) Refaça o sunburst | |
# substituir NAs em colunas de caracter por vazio | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment