Hoje vamos dar continuidade com as geometrias do ggplot e ver algumas funcionalidades, inclusive criar gráficos animados para utilizar em apresentações e websites. Mãos à obra.
Se você se lembra do encontro de ontem, terminamos nosso dia vendo uma geometria para duas variáveis, sendo uma contínua e outra discreta. Começamos hoje falando de outra geometria que se aplica a estes casos. Talvez já tenha visto isso, inclusive, nas suas aulas de estatística e sofrido para calcular os intervalos interquartis, limites superior e inferior, mediana … O R irá construir tudo isso com uma linha de comando!
# Carregando nossas bibliotecas
library(tidyverse)
library(tidylog)
library(nycflights13)
Para entender, o boxplot descreve aquela distribuição da variável contínua não mais como uma curva de densidade, mas representando medidas de resumo desta distribuição. Ou seja, linha vertical (ou horizontal, caso deseje inverter a orientação da ‘caixa’) será uma medida resumo da distribuição, sendo a primeira linha o limite inferior, a segunda (já na ‘caixa’) o 1° quartil (25% da distribuição), a terceira o 2° quartil/mediana (50% da distribuição), a terceira linha o 3° quartil (75% da distribuição) e a última linha (já fora da caixa) será o limite superior. Se houver pontos (‘outliers’) fora dos limites inferior e superior, serão representados por pontos.
# Boxplot da relação entre 'origin' e 'dep_time'
flights %>%
ggplot() +
geom_boxplot(aes(x = origin, y = dep_time))
O que temos neste boxplot? Como tenho três origens possíveis (valores que a variável ‘origin’ assume), o R desenhou 3 boxplots da distribuição da hora de partida dos voos em cada um dos aeroportos. Olhando especificamente para ‘EWR’, temos que os voos começam todos no mesmo horário/ou muito próximos, pois o limite inferior é o mesmo (a escala do eixo y e a grade talvez estejam ruins - mas podemos mudar isso). Dos voos partindo de ‘JFK’, metade deles ocorrem após as 15h e metade antes das 15h; enquanto que o trânsito de aeronaves é mais intenso antes das 15h para os outros dois aeroportos. PS: caso queira saber o que significa cada variável do banco flights, help(flights).
Mas de toda forma, não é um curso de estatística. Para saber mais sobre boxplot talvez tenha que ler um pouco sobre essa área. Na linha de comando, fica bem fácil.
Os gráficos que vimos até agora (histograma, densidade, bloxplot) produziram gráficos que mostravam distribuições de múltiplas observações para cada categoria da variável discreta. Mas e quando só temos uma categoria nesta outra variável discreta? O que acontece com a representação gráfica da distribuição da variável contínua? Usaremos uma geometria de coluna (geom_col) e, neste caso, costuma exigir a manipulação de nossos dados com group_by() e summarize(). Sim, ontem você não precisava disso e agora talvez fique mais claro.
Para construir um gráfico de coluna você precisará colapsar todas as informações para reter uma única linha/observação por grupo(aka valor assumido pela variável discreta). Assim, vamos alterar a unidade de análise e reduzir o tamanho do nosso banco.
Imagine que você queira tirar o valor médio do tempo de atraso dos voos em cada um dos 3 aeroportos de Nova Iorque. Seria uma única medida (média) por aeroporto(variável discreta), certo? Mas para alcançar a média, precisaria fazer o summarize(mean()) primeiro. Perceba que agora não quero o número de voos (como pedi que fizesse ontem), mas sim, uma medida resumo da média do tempo de atraso.
E como ficaria?
# Média de atraso por aeroporto NYC
flights %>%
group_by(origin) %>%
summarize(atraso_medio = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_col(aes(x = origin, y = atraso_medio))
Agora as coisas ficam interessantes. Veja que até então, estávamos trabalhando com distribuições de uma única variável, ou de uma variável contínua compartimentalizada em vários grupos (que eram os valores que a variável discreta assumia). Agora, teremos como um cruzamento do eixo x e do eixo y, quando duas variáveis contínuas se encontram. A geometria padrão utilizada para visualizar este tipo de relação é o gráfico de dispersão (aka gráfico de pontos - geom_point), onde cada ponto representa o par de informações que se cruzam. Quase como um jogo de batalha naval, onde o espaço bidimensional acontece para localizar o encontro das variáveis.
Vejamos um exemplo. Imagine que queremos visualizar a relação entre ‘distance’(eixo x) e ‘air_time’ (eixo y). Diferentemente dos exemplos anteriores, o número possível de pares pode exigir de sua máquina, então, extraia uma amostra aleatória simples se tiver demorando (mantive como # comentário no código).
# Gráfico de pontos 'distance' por 'air_time'
flights %>% # sample_n(1000) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time))
O resultado está um pouco ruim, não? Pontos estão muito grandes. Fica difícil de visualizar cada relação ‘distance’ x ‘air_time’ dos voos. Mas, ainda assim, você consegue perceber que quanto maior a distãncia…. o que acontece com o tempo? Mas vamos tornar esse gráfico mais bonito, certo? Vamos alterar a forma e tamanho dos pontos.
# Alterando parâmetros dependentes do gráfico de pontos
flights %>% # sample_n(1000) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time), size = 0.1, colour = "blue")
Lembre-se disso. Diferentemente de editores de planilha, o R produz resultados acabados. Não podemos editar o que foi feito, embora possamos facilmente produzir um gráfico melhorado. Há ganhos nisso! Tanto em velocidade, escalabilidade, reprodutibilidade, memória do que foi feito e segurança.
Então, é natural que você teste várias formas e múltiplas vezes até encontrar a formatação adequada e que mais te satisfaça. E, por isso, vamos mudar a forma como os pontos estão representados usando o parâmetro/atributo ‘shape’ - que é um parâmetro fixo, certo!? Só um detalhe aqui, que talvez você deva olhar lá na documentação do pacote ou no mapa mental que indiquei (cheatsheets). Os diferentes formatos (‘shape’) são representados por um índice numérico, então, você verá ‘shape’ = número.
# Alterando parâmetros dependentes do gráfico de pontos
flights %>% # sample_n(1000) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time), size = 0.1, colour = "blue", shape = 2)
Certo, muitos pontos dificultam a escala para visualizar o ‘shape’ de cada ponto. Vamos em frente.
A relação entre duas variáveis contínuas pode, ainda, ser representada a partir de modelos lineares e não lineares. Ou seja, podemos fazer uma regressão nestes dados e encontrar a reta/curva que melhor se ajusta aos dados. O R faz isso para você também com a geometria geom_smooth().
Para isso, você só precisa indicar dentro dos parâmetros desta geometria qual é o método (‘method’) para modelar seus dados. O mais usual, como talvez deva saber, é a regressão linear (‘linear model’) que você escreve “lm” (method = “lm”). Veja como ficaria:
# Gráfico de dispersão de 'distance' por 'air_time' com a reta de regressão linear
flights %>% # sample_n(1000) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time), size = 0.1) +
geom_smooth(aes(x = distance, y = air_time), method = "lm", se = FALSE)
Veja só uma coisa. Você poderia ter calculado a regressão linear das variáveis ‘distance’ e ‘air_time’ sem usar o ggplot. Para isso, você tem a função lm(), que te retorna a tabela com os alfas, betas etc. Mas você não precisa rodar o lm() antes para criar o gráfico, percebe? O próprio ggplot fará o cálculo e vai gerar a reta no seu gráfico. Caso você desejasse usar lm() primeiro, seu código ficaria redundante e você não saberia que parâmetros informar dentro de geom_smopth() - que só aceita as variáveis brutas e não o resultado de um lm().
Mas apareceu um atributo/parâmetro fixo novo aí, certo? Talvez você já tenha usado help() (parabéns!) e descoberto que se trata do standard error, ou erro padrão. Este admite o valor boleano de verdadeiro ou falso, ou seja, caso você coloque ‘se = TRUE’ (ou retirar o atributo, pois o default é se = TRUE) no parâmetro fixo, o resultado será diferente. A reta agora passará a incluir um intervalo de confiança (95%) ao redor da reta. Veja como fica.
# Construindo gráfico de dispersão e reta de regressão com SE - para uma amostra
flights %>% sample_n(50) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time), size = 10/100) +
geom_smooth(aes(x = distance, y = air_time), method = "lm", se = TRUE)
Ficou legal, não?! Certo, vamos ver a alternativa que faz uso de outro método para traçar a regressão de ajuste. A mais utilizada é a regressão local com pesos - ou método loess (‘local weighted regression’). Veja que o resultado não diverge muito da regressão linear, que ajusta para uma reta. Assim, podemos ver que o ajuste funcionaria bem para uma regressão linear nos dados:
# Construindo gráfico de dispersão e curva de regressão com SE - para uma amostra
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time), size = 10/100) +
geom_smooth(aes(x = distance, y = air_time), method = "loess")
Faça você mesmo
Faça um gráfico de densidade que mostre a distribuição da hora da partida por companhia aérea, considerando somente os voos que partiram de ‘EWR’ e pousaram em ‘BOS’. Dica: Use geom_density() e veja os nomes dos parâmetros que ela aceita - não é preciso usar group_by().
Faça um gráfico de colunas (geom_col) com a duração média de voo (air_time) por companhia aérea (carrier). Dica: Neste caso, precisamos calcular a média de cada grupo antes de informar à geometria de colunas.
Faça um gráfico que represente a relação entre atraso na partida (‘arr_delay’) e na chegada (‘dep_delay’), somente para os voos saindo de ‘JFK’.
Normalmente, construir representações visuais de três ou mais variáveis é um desafio e pode ocasionar mais desinformação que informação. Isso acontece, pois estamos limitados a realidades bidimensionais no papel e nas telas. Então, toda representação gráfica neste sentido deve ser feita com o devido cuidado. Mas vamos aprender alguns truques que podem ser bem úteis.
Podemos incluir variáveis como parâmetros de estilo de nossas geometrias, ou seja, cores podem representar de qual aeroporto de origem estamos falando nas colunas; o raio do ponto (aka círculo) que representa cada país num gráfico de dispersão pode variar de tamanho conforme a população deste país; quadrados podem fazer referência aos voos que partiram pela manhã, losangos nos que partiram à tarde e circunferências nos que partiram à noite…
Vamos ver como ficaria? No exemplo, um gráfico de dispersão com ‘dep_time’ vs ‘dep_delay’ dos voos, com o raio do círculo sendo a distancia ‘distance’:
# Gráfico de dispersão 'dep_time' vs 'dep_delay', com a distância no tamanho dos pontos
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay, size = distance))
## sample_n: removed 335,776 rows (>99%), 1,000 rows remaining
## Warning: Removed 18 rows containing missing values (`geom_point()`).
Agora, ao invés de alterar o tamanho destes pontos, e se usarmos as cores ou formas para representar os aeroportos de origem de cada voo?
# Gráfico de dispersão 'dep_time' vs 'dep_delay' com cores dos aeroportos de origem
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay, color = origin))
Legal né? Lembre-se que como estamos usando os atributos/parâmetros estéticos em variáveis, eles não poderiam ser parâmetros fixos! E é por serem parâmetros dependentes que vão escritos dentro da função ‘aesthetics’ - aes().
# Com shapes invés de colors
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay, shape = origin))
Aqui temos uma ferramenta muito bacana quando trabalhamos com dados. Ela permite que você crie múltiplos gráficos que são exibidos lado a lado e facilitam a percepção das mudanças em alguma variável de interesse. O legal é que basta incluirmos a função facet_grid() ao final do seu bloco de cógido - como mais uma camada -, que o R faz o resto automaticamente.
Como atributo da função facet_grid() você pode definir uma variável discreta na qual deseje separar seus dados. Ou seja, ela funcionaria como um group_by() visual, já que faria gráficos iguais para diferentes grupos possíveis de uma variável discreta de interesse. Por exemplo, poderia construir gráficos de dispersão da relação entre ‘dep_time’ e ‘dep_delay’ para cada aeroporto de origem, mas ao invés de usar ‘origin’ como ‘shape’ ou ‘colour’, irei colocar os gráficos resultantes lado a lado para facilitar a comparação. Veja como ficaria:
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay)) +
facet_grid(cols = vars(origin))
Agora, caso você queira mudar a orintação das imagens, basta fazer uso dos atributos ‘rows’ e ‘cols’, como no exemplo que segue. Veja o que mudou.
# Orientação horizontal
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay)) +
facet_grid(rows = vars(origin)) # cols virou rows
Fácil, certo!? Caso você queira produzir ‘facetas’ diferentes a partir de mais variáveis, você poderia incluir dentro da função vars() os nomes delas separadas por vírgulas. Mas atenção!!! O problema passa a ser o tamanho do resultado, que pode ficar ilegível.
Para facilitar a visualização, você pode indicar uma variável para criar facetas horizontais e outra para criar as facetas na orientação vertical. Vamos usar ‘origin’ e ‘month’, pois são variáveis discretas com poucos valores possíveis. Veja como fica:
# Facet_grid do gráfico de dispersão em duas orientaçoes
flights %>%
sample_n(1000) %>%
ggplot() +
geom_point(aes(x = dep_time, y = dep_delay)) +
facet_grid(rows = vars(month), cols = vars(origin))
Este tipo de geometria vai exigir, normalmente, uma preparação dos dados que deseja representar. Embora a variável do eixo x possa ser contínua ou discreta, o gráfico somente fará sentido se você ordenar os valores -, do contrário as linhas que ligam os pontos farão um zigue-zague.
Então, vamos criar tentar um gráfico de linhas para o atraso médio mensal dos voos. O caminho correto é transofrmar a variável ‘month’ (que deve estar como ‘numeric’ no banco ‘flights’) em um ‘factor’ ordenado. Feito isso, podemos calcular o atraso médio com summarize(mean()).
# Corrigindo os dados - month para factor e extraindo média
flights %>%
mutate(month = factor(month, levels = 1:12, ordered = T)) %>%
group_by(month) %>%
summarize(media_atraso = mean(dep_delay, na.rm = TRUE))
Pronto, os dados estão em formato apropriado para unidade de análise sendo o mês com o atraso médio sendo nossa variável de interesse. A sintaxe da geometria de linha é um pouco mais difícil, exigindo que você indique uma variável ‘x’, um ‘y’ e um group - que será a forma pela qual a função deve unir os pontos. Como no exemplo, temos somente um grupo/linha, então ‘group’ assume 1.
# Gráfico de linhas
flights %>%
mutate(month = factor(month, levels = 1:12, ordered = T)) %>%
group_by(month) %>%
summarize(atraso_media = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_line(aes(x = month, y = atraso_media), group = 1)
Vamos exercitar. Como fazemos para ter uma linha para cada aeroporto de origem? Repita o ajuste prévio dos dados e use o atributo ‘group’ para definir a variável ‘origin’. Lembre-se que agora, o ajuste exige também que você agrupe por ‘origin’. Então, precisamos usar o group_by() com ‘month’ e ‘origin’, para depois inserir ‘origin’ como atributo ‘group’ dentro do geom_line(aes()) . Veja como ficaria:
# Gráfico de linhas por aeroporto de origem
flights %>%
mutate(month = factor(month, levels = 1:12, ordered=T)) %>%
group_by(month, origin) %>%
summarize(atraso_medio = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_line(aes(x = month, y = atraso_medio, group = origin))
Certo, mas como você sabe qual linha é qual aeroporto? Vamos colocar ‘colour’/‘color’ como atributo dependente também. Aí sim a visualização ficará boa.
# Gráfico de linhas por aeroporto (acabado)
flights %>%
mutate(month = factor(month, levels=1:12, ordered = T)) %>%
group_by(month, origin) %>%
summarize(atraso_medio = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_line(aes(x = month, y = atraso_medio, group = origin, color = origin))
Sem dúvida este gráfico de linha é o mais confuso, certo? Então, talvez seja bom olhar a tabela que resulta do ajuste prévio. Como você achava que seria a tabela resultante do ajuste prévio do exemplo anterior? Veja só.
flights %>%
mutate(month = factor(month, levels = 1:12, ordered = T)) %>%
group_by(month, origin) %>%
summarize(atraso_medio = mean(dep_delay, na.rm = TRUE))
## mutate: converted 'month' from integer to ordered factor (0 new NA)
## group_by: 2 grouping variables (month, origin)
## summarize: now 36 rows and 3 columns, one group variable remaining (month)
## # A tibble: 36 × 3
## # Groups: month [12]
## month origin atraso_medio
## <ord> <chr> <dbl>
## 1 1 EWR 14.9
## 2 1 JFK 8.62
## 3 1 LGA 5.64
## 4 2 EWR 13.1
## 5 2 JFK 11.8
## 6 2 LGA 6.96
## 7 3 EWR 18.1
## 8 3 JFK 10.7
## 9 3 LGA 10.2
## 10 4 EWR 17.4
## # ℹ 26 more rows
Outro gráfico que você já deve ter visto é o de barras 100%, ou seja, aqueles gráficos onde todas as barras têm a mesma altura e seu preenchimento funciona como porcentagens de alguma variável. Para construir estes gráficos, usamos as mesmas etapas que acabamos de ver. É preciso que os valores que vão preencher as colunas representem a contribuição de cada grupo (possibilidades de uma variável) para o total daquela variável.
Imagine, por exemplo, que você queira a contribuição de cada aeroporto de origem para o atraso total do mês dos voos que partem de Nova Iorque. Assim, cada um dos 3 aeroportos seria parte do preenchimento da coluna de cada mês, certo? Então, precisaria da soma dos atrasos em cada mês e a soma de cada aeroporto em cada mês. Veja que aqui estamos precisando usar o group_by() para aplicar a somatória summarize(sum()) a cada grupo de aeroportos. De posse destas informações, é só trocar geom_line() por geom_col() - que já vimos.
# Gráfico de barras 100% do atraso médio mensal por aeroporto
flights %>%
mutate(month = factor(month, levels = 1:12, ordered = T)) %>%
group_by(month, origin) %>%
summarize(atraso_medio_total = sum(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_col(aes(x = month, y = atraso_medio_total, fill = origin), position = "fill")
Se você não entendeu, tente executar o código sem o gráfico e veja a tabela resultante. Mas ainda assim, temos um atributo/argumento novo, certo? Ocorre que podemos utilizar ‘position’ para comparar as barras de maneira relativa em porcentagem, mas para isso, ‘position’ precisa ser = ‘fill’. Veja help(geom_col) e o material de apoio indicado.
Mas veja, é preciso cuidado ao usar este tipo de gráfico. Seus valores do eixo y totalizam 100%, o que implica que não saberá mais o valor absoluto mensal. Se, por exemplo, fereiro teve 100 voos e março 5.000… isso você não irá saber, pois ambas colunas irão totalizar 100%. Então, cuidado.
Um gráfico equivalente a este é o gráfico de pizza (arghh!!!), que deve ser usado com cuidado pelos mesmos motivos. Mas veja como é simples para gerar um gráfico de pizza a partir de um gráfico de 100% de colunas.
A primeira tarefa, então, é gerar uma tabela que funcione para este gráfico. Novamente, temos um trabalho prévio. Após isso, vamos usar geom_col() como faríamos antes, mas a diferença é que agora iremos restringir a variável no eixo x, já que o gráfico de pizza é equivalente a ‘uma só barra’. Perceba também que nossa variável ‘x’ ficará vazia, já que como disse teremos somente uma barra.
# Gráfico de coluna única 100%
flights %>% group_by(origin) %>%
summarize(atraso_medio_total = sum(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_col(aes(x = "", y = atraso_medio_total, fill = origin), position = "fill")
Não saiu uma pizza, não é mesmo? Isso por que falta adicionar uma camada, para que o R compreenda que precisa mostrar esse resultado no formato circular.
Para entendermos isso, precisamos falar um pouco de outro elemento da representação gráfica e do ggplot: o sistema de coordenadas. Se você tem interesse em mapas, saiba que o ggplot faz parte deste mundo junto com outros pacotes. Mas voltando… Normalmente não é preciso especificar o sistema de coordenadas para construir gráficos, pois elas são default em espaços iguais verticais e horizontais. Entretanto, quando queremos representar informações em formato de um círculo, aquilo que era uma medida linear passa a ser uma métrica angular. O sistema de coordenadas ‘polares’, portanto, divide o espaço em graus de um círculo.
Na prática, definimos um novo sistema de coordenadas ao adicionar mais uma camada ao bloco de código do ggplot com a função coord_polar(), onde o atributo/parâmetro ‘theta’ diz respeito ao angulo Se definirmos um sistema de coordenadas polares adicionando mais uma camada coord_polar(), e definimos o ángulo theta de cada fatia baseado na variável de interesse. Se nossa variável y é dep_delay, e queremos a ‘fatia’ da pizza desta variável, então o ângulo ‘theta’ será = ‘y’. (Entre aspas, por que acabamos de criar y).
# Gráfico de pizza
flights %>%
group_by(origin) %>%
summarize(atraso_medio_total = sum(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_col(aes(x = "", y = atraso_medio_total, fill = origin), position = "fill") +
coord_polar(theta = "y")
Como havia adiantado para você, há uma imensidão de possibilidade no ggplot e infelizmente não conseguiremos cobrir tudo. Mas uso este espaço para mostrar algumas coisas. O primeiro exemplo é o geom_text(), que permite que ao invés de ‘shapes’ como formas geométricas, é o próprio texto que é inserido no gráfico. Costumam ser bem úteis para representar séries temporais ou situar países/lugares/nomes num continuum. Vejamos um exemplo, onde o nome do destino é inserido no gráfico de dispersão da relação entre ‘dep_time’ e ‘dep_delay’.
flights %>%
sample_n(100) %>%
ggplot() +
geom_text(aes(x = dep_time, y = dep_delay, label = dest))
## sample_n: removed 336,676 rows (>99%), 100 rows remaining
## Warning: Removed 7 rows containing missing values (`geom_text()`).
Outra geometria que usamos bastante com mapas é a geom_tile(), mas infelizmente não temos tempo de falar aqui. Mas para que compreenda, ela constrói uma mapa de calor da incidência da relação entre duas variáveis. No nosso exemplo, especificamos duas variáveis ‘origin’ e ‘month’ para serem contrastadas, e a intensidade da cor de cada quadrado diz respeito ao valor médio de atraso na decolagem. Com isso, visualizamos o atraso médio mensal por aeroporto de origem.
# Mapa de calor
flights %>%
group_by(origin, month) %>%
summarize(atraso_decolagem_medio = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_tile(aes(x = origin, y = month, fill = atraso_decolagem_medio))
Quando é o pior momento para se voar? Se você disse Dezembro, repense.
Sem dúvida, você terá desafios na hora de escolher as cores de seu gráfico. Especialmente, se você - como eu - não for designer. Mas para nossa sorte, há ferramentas prontas para fazer isso por nós e escolher uma estética de maneira melhor acabada e sistematizada. O Color Brewer é um guia excelente e vale muito a pena ser favoritado.
Talvez você não tenha favoritado, então me deixe convencer você.
Para especificar cores nos nossos gráficos, o ggplot admite uma camada específica, que será preenchida pela função scales() (escalas).
Precisamos tomar muito cuidado com o tipo de scale, que precisa corresponder ao tipo da nossa variável e também se estamos colorindo um ponto/linha (‘colour’) ou preenchendo uma área (‘fill’). Sempre use a tabela abaixo como guia:
| TIPO | Colour/Color (Linha/Ponto) | Fill (Área) |
|---|---|---|
| Discreta | scale_color_brewer(palette = “pré-ajustada”) | scale_fill_brewer(palette = “pré-ajustada”) |
| Contínua | scale_color_gradient(low = “cor1”, high = “cor2”) | scale_fill_gradient(low = “cor1”, high = “cor2”) |
Você precisará sempre obedecer certos parâmetros no scales, conforme o tipo da variável, se se trata de uma linha/ponto (que vão admitir ‘color’, mas não ‘fill’) ou áera (‘fill’). Pode seguir a lógica acima, onde você escolhe se usa o ‘scale_fill_brewer’ (com paletas de cores pré-definida - veja lá no site indicado) ou se utiliza o ‘scale_color_gradient’ (com a definição das cores que ficam nos extremos do seu gradiente, pelo menos). Você pode definir as cores as nomeando, ou usando um código dos diversos sistemas de referência de cores - por exemplo, “blue” = rgb(3,78,252) = hex(#034efc). Evidentemente que não decoramos isso, tão pouco sabemos de cor todos os nomes das cores que o R vai aceitar. POR ISSO, FAVORITE O SITE e use o código que ele te fornecerá ao escolher a cor. Acho que agora te convenci, então aproveite e faça uso de uma das várias paletas de cores pré-definidas.
Agora, vamos treinar. Vamos construir, com as cores default, um gráfico de dispersão (geom_points) do contraste entre ‘distance’ e ‘air_time’, usando a variável de hora de partida na estética de cores.
# Gráfico de dispersão com a 3ª variável dep_time na estética de cores
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = dep_time))
## sample_n: removed 336,276 rows (>99%), 500 rows remaining
## Warning: Removed 10 rows containing missing values (`geom_point()`).
Até que não é feio, certo? Mas vamos treinar e inserir uma escala de vermelho. Se você se perguntou como inseri estes códigos de cores, volte duas casas.
# Com escala de vermelho
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, color = dep_time)) +
scale_color_gradient(low="#fee0d2", high="#de2d26")
## sample_n: removed 336,276 rows (>99%), 500 rows remaining
## Warning: Removed 14 rows containing missing values (`geom_point()`).
Percebeu que entre os valores extremos, o R automaticamente ajusta os demais valores para tons dentro deste gradiente? Bacana demais, né?! E se você quisesse cores para uma variável discreta? Ou seja, uma variável que não tem hierarquia/continuidade entre os valores possíveis que apresenta? Neste caso, cada valor da variável assumiria uma cor diferente - e não um gradiente. Evidentemente, que a sua tarefa de encontrar cores vai ficando difícil a medida em que os valores possíveis da variável discreta aumentam. Mas, de qualquer forma, há paletas de cores para variáveis discretas também!!! Se você observou o site com atenção, nas opções do lado esquerdo, você pode inserir o número de classes (valores possíveis da sua variável), natureza da sua variável (sequencial, divergente, qualitativa), paleta de espectro numa única cor ou em mais de uma, o tipo de sistema de referência (códigos HEX, RGB, CMYK), opções para cores amigáveis a determinados tipos de deficiência…
Mas caso você queira inserir essas escolhas automaticamente no seu código, basta usar os atributos da função scale_color_brewer(). Para nós, vamos usar ‘palette’ para determinar que queremos uma paleta para uma variável qualitativa: help(scale_color_brewer).
# Incorporando uma escala de cores discreta
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, color = origin)) +
scale_color_brewer(palette = "Set2")
## sample_n: removed 336,276 rows (>99%), 500 rows remaining
## Warning: Removed 18 rows containing missing values (`geom_point()`).
Certo, e caso queiramos usar o parâmetro ‘fill’ para preencher uma área, como fizemos no mapa de calor logo acima? Mas agora usando uma escala de cores para completar os espaços? O atributo ‘fill’ seria minha variável contínua de interesse e usaria ‘scale_fill_gradient’ para atribuir a escala de cores.
flights %>%
group_by(origin, month) %>%
summarize(atraso_medio_decolagem = mean(dep_delay, na.rm = TRUE)) %>%
ggplot() +
geom_tile(aes(x = origin, y = month, fill = atraso_medio_decolagem)) +
scale_fill_gradient(low="#fee0d2", high="#de2d26")
Certo, vimos muita coisa até agora, mas nada sobre como colocar ‘títulos’, ‘nomes dos eixos’, ‘legendas’ etc. Mas como você já viu, para adicionar algo no ggplot, devemos adicionar por meio de uma nova camada. Obs. Há alguns atributos de geometrias específicas que admitem que você insira estas informações, mas vamos trabalhar aqui com a regra geral.
Primeiro, como colocar um título no gráfico?
# Inserindo título
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, color = origin)) +
ggtitle("O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um")
E para modificar os rótulos (‘labels’) dos eixos x e y? Para isso, usamos as funções xlab() e ylab(), que por default são os nomes das suas variáveis. O que nem sempre é claro para comunicar, já que “V23” ou “cod_mun_ibge” não são estéticas apropriadas.
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y")
Agora, caso queiramos mudar o lugar onde a legenda aparece? Simples, outra camada.
# Mudando a legenda
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y") +
theme(legend.position="bottom")
Forçando, você pode modificar os elementos da sua figura. Por exemplo, o tamanho do texto dos seus rótulos está ruim? Podemos alterar.
# Alterando tamanho do texto dos rótulos
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y") +
theme(axis.text.x = element_text(size = 3),
axis.text.y = element_text(size = 3),
axis.title.x = element_text(size = 3),
axis.title.y = element_text(size = 3))
Bastante esforço, você deve ter imaginado. Já que cada elemento que eu queira alterar, vai demandar uma camada/função. Mas temos solução para isso também. Há temas pré-configurados que podemos fazer uso. Basta que você, no lugar de todas as características estéticas da sua imagem, insira o nome do tema. A facilidade do RStudio propicia que você comece escrevendo theme_ e ele autocomplete para você.
Há alguns já pré-instalados no ggplot, mas vale a pena tentar instalar o pacote ggthemes. Só para ter uma ideia, com uma palavra o estilo da revista “The Economist” será o adotado para seu gráfico!
install.packages("ggthemes")
library(ggthemes)
# Inserindo tema do The Economist
flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y") +
theme_economist()
E mesmo pré-carregada, se não gostou de algo, você ainda pode alterar os parâmetros!
Você deve ter percebido que nenhum dos gráficos que fizemos no tutorial foi salvo lá no seu Global Environment. Já havia adiantado para você que nós deixaríamos de criar objetos na análise de dados, quando estivéssemos trabalhando com gráficos. Isso por que, ao executar o bloco de código do gráfico ele é gerado e vai para sua janela direita inferior (‘plots’) se tiver usando script e aparece no corpo do chunk se tiver usando o RMarkdown.
Mas ainda falta dizer como você salva a figura que você criou. A boa notícia que é bem simples, bastando uma linha com a função ggsave() e suas figuras são salvas em .png, .jpg, .pdf etc. A extensão do arquivo e a resolução podem ser facilmente alteradas. Veja o código abaixo - Ah, se você está usando um Projeto, ele vai automaticamente para lá. Se usar o setwd(), o R salva na sua pasta de working directory por default.
# Salvando seus gráficos
flights %>% ggplot() +
geom_bar(aes(x = origin))
ggsave("voos_graficobarras.png", scale = 2, dpi = "300") # Veja help(ggsave)
Rapidamente, pois o tutorial está muito longo. Para produzir gráficos interativos, podemos usar o pacote ploty, a partir da função ggploty(). Você precisará fazer o gráfico normalmente na sintaxe do ggplot e depois fazer uso do ggploty().
# Construindo gráfico interativo
install.packages("plotly")
## Installing package into '/home/vinicius/R/x86_64-pc-linux-gnu-library/4.3'
## (as 'lib' is unspecified)
library(plotly)
##
## Attaching package: 'plotly'
## The following objects are masked from 'package:tidylog':
##
## distinct, filter, group_by, mutate, rename, select, slice,
## summarise, transmute, ungroup
## The following object is masked from 'package:ggplot2':
##
## last_plot
## The following object is masked from 'package:stats':
##
## filter
## The following object is masked from 'package:graphics':
##
## layout
grafico_interativo <- flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y") +
theme_classic()
## sample_n: removed 336,276 rows (>99%), 500 rows remaining
E agora, a mágica! Use seu mouse para explorar o gráfico abaixo.
# Construindo interação
grafico_interativo %>%
ggplotly()
Mas interativo é pouco. Você pode construir gráficos animados com o mesmo pacote ploty. A única diferença para a sintaxe que fizemos acima é que, para animações é preciso informar o atributo/parâmetro ‘frame’ na geometria. Isso permite que a variável seja definida como ‘tempo de transição’ da animação. Veja o exemplo em que a variável ‘month’ é nosso ‘frame’. Pode clicar no play e ver a mágica - mas atenção: Só funciona em html, por isso, você enxerga no RMarkdown.
# Construindo gráfico
grafico_animado <- flights %>%
sample_n(500) %>%
ggplot() +
geom_point(aes(x = distance, y = air_time, colour = origin, frame = month)) +
ggtitle(label = "O título que você quiser, mas que seja explicativo!!!", subtitle = "caso precise de um") +
xlab("nome da variável do eixo x") +
ylab("nome da variável do eixo y") +
theme_classic()
## sample_n: removed 336,276 rows (>99%), 500 rows remaining
## Warning in geom_point(aes(x = distance, y = air_time, colour = origin, frame =
## month)): Ignoring unknown aesthetics: frame
# Animando o resultado
grafico_animado %>%
ggplotly()
Ficamos por aqui.
Obrigado pela trajetória!