Visualizando dados geoquímicos com o ggplot2
Introdução
Nesta aula, continuaremos trabalhando com o conjunto de dados de MORBs e OIBs que organizamos e limpamos na aula anterior. Para garantir que todos estejam usando as mesmas tabelas, os arquivos desta aula estão disponíveis para download nos seguintes links: MORBs e OIBs.
O objetivo desta aula é produzir gráficos com o pacote ggplot2, com foco em diagramas de dispersão (scatterplots), amplamente utilizados em geoquímica. Esses diagramas servirão como base para aprendermos a gramática dos gráficos.
Importando os dados
Primeiramente, vamos importar os dados com a função read_excel():
Uma maneira eficiente de lidar com esses dados é combiná-los em uma única tabela. Primeiramente, vamos começar criando uma coluna tipo usando o verbo mutate() do dplyr. Isso vai nos ajudar a diferenciar a origem dos dados.
Agora, vamos usar a função bind_rows() do dplyr para combiná-las em uma nova tabela: dados. O que acontece quando executamos o código abaixo?
Um erro acontece porque a coluna age de morbs e oibs não é equivalente: em um caso, os dados são do tipo character, e no outro, numeric. Vamos inspecionar esse problema com mais detalhes:
O problema principal é que age em oibs se refere ao tempo geológico, enquanto em morbs representa idades absolutas. Podemos renomear age em oibs para algo que descreva melhor essa coluna:
Agora, se executarmos novamente o código anterior, conseguiremos criar a tabela combinada:
Gramática dos gráficos
De maneira simplificada, o código para criar um gráfico com o ggplot2 responde a três perguntas principais:
- Quais dados vamos usar?
- Quais variáveis queremos mostrar?
- Como essas variáveis serão representadas visualmente?
Todo gráfico começa com a seguinte estrutura:
ggplot(data = dados, aes(...)) +
geom_...ou, usando pipe:
dados |>
ggplot(aes(...)) +
geom_...Em data, escolhemos a tabela com a qual vamos trabalhar. Em aes (aesthetic mappings), definimos quais variáveis da tabela serão usadas no gráfico. As variáveis necessárias dependem do tipo de gráfico que queremos construir.
Já geom_ se refere à geometria, isto é, à forma como os dados serão representados visualmente. Há diferentes tipos de geometria:
geom_point()geom_line()geom_bar()geom_histogram()geom_boxplot()- etc.
Scatterplots
Para criar scatterplots, precisamos de duas variáveis: uma para o eixo x e outra para o eixo y. Nesse tipo de gráfico, os dados são representados como pontos usando geom_point().
Assim, se quisermos visualizar Fe2O3T vs. MgO usando os dados da tabela oibs, podemos executar o seguinte código:
Observe que recebemos um aviso informando que há linhas com dados ausentes. Isso ocorre porque geom_point() não consegue desenhar pontos quando alguma das variáveis é NA.
A função geom_point() possui o parâmetro na.rm, que podemos definir como TRUE para remover esses valores ausentes durante a criação do gráfico:
Uma das ideias centrais do ggplot2 é que gráficos são construídos em camadas.
No exemplo anterior, criamos um gráfico com uma única camada: os pontos representados por geom_point().
No entanto, podemos adicionar novas camadas ao mesmo gráfico sem precisar recriá-lo. Por exemplo, podemos incluir uma linha de tendência com geom_smooth():
Agora o gráfico possui duas camadas:
- pontos (os dados observados)
- linha de tendência
Cada nova camada é adicionada com o operador +.
Isso significa que um gráfico no ggplot2 é construído de forma incremental: começamos com uma base e adicionamos elementos visuais conforme necessário.
Mapeando variáveis
Até agora, usamos aes() apenas para definir as variáveis nos eixos x e y. No entanto, o mapeamento estético pode ser usado para representar outras dimensões dos dados.
Por exemplo, podemos usar cores para representar uma terceira variável:
Nesse caso, cada cor corresponde a uma categoria diferente da variável tectonic_setting. Isso permite visualizar padrões adicionais que não seriam visíveis apenas com os eixos x e y.
Como muitos pontos ficam próximos um do outro, nós podemos melhorar a visualização ajustando a transparência com o parâmetro alpha de geom_point():
Se quisermos ver a diferença entre morbs e oibs, podemos usar a tabela dados que criamos no início desta aula e mapear a coluna tipo para color:
Para mudar o formato dos pontos, podemos usar o parâmetro shape:
Customização básica
Até aqui, focamos principalmente em plotar dados. Mas gráficos são uma combinação de ciência e arte. Por exemplo, algo que podemos melhorar nos nossos gráficos são os rótulos dos eixos.
Podemos ajustar os rótulos com labs():
Nós podemos também mudar o título da legenda com labs(). Basta darmos um rótulo para color e shape:
Até então o ggplot2 vem escolhendo a cor e o símbolo dos pontos quando mapeamos color e shape. Se quisermos especificar que cor e símbolo queremos, podemos usar scale_color_manual() e scale_shape_manual(), respectivamente.
Vamos deixar OIBs como azul claro e MORBs como salmão. Você pode ver uma lista de cores disponíveis neste link.
Agora, vamos mudar o símbolo de OIBs para círculos e de MORBs para triângulos. Vamos nos guiar pela imagem abaixo:
Temas
Também podemos customizar outros aspectos do gráfico, como a cor de fundo e a aparência dos eixos. A maneira mais simples de fazer isso é usando temas. Você pode acessar este link para ver os temas disponíveis.
Vamos ver como usá-los. O código abaixo adiciona o theme_bw() ao nosso plot. Com base no link acima, experimente usar outros temas, substituindo theme_bw() pelo tema que você desejar.
Além dos temas que vêm com o ggplot2, você pode instalar o pacote ggthemes para ter acesso à mais opções.
Herança de argumentos
Até então, em todos os exemplos que vimos, definimos argumentos globais dentro da função ggplot(), como o conjunto de dados (data) e aes(). Esses argumentos são automaticamente herdados pelas camadas adicionadas com geom_point() e outras geometrias. Por exemplo:
No entanto, essa não é a única forma de trabalhar: também podemos definir data e aes() individualmente em cada camada:
No exemplo acima, não definimos nenhum argumento global. Isso é útil quando queremos especificar argumentos diferentes para cada camada.
No início desta aula, juntamos as tabelas de morbs e oibs para facilitar a criação dos gráficos. No entanto, também poderíamos usar um geom_point() para cada tabela:
O código acima plota os pontos de morbs e oibs com os mesmos símbolos e cores. Em exemplos anteriores, vimos que podemos associar um parâmetro como color à uma variável do conjunto de dados, colocando-o dentro de aes(), por exemplo, aes(color = tipo).
Quando fazemos isso, o ggplot2 irá variar automaticamente a cor de acordo com os valores dessa variável e criar uma legenda.
Por outro lado, quando definimos color fora de aes(), estamos fixando um valor constante, que será aplicado igualmente a todos os pontos daquela camada, sem relação com os dados:
Uma limitação dessa abordagem é que o ggplot2 não cria automaticamente uma legenda quando definimos color (ou outras propriedades, como shape e fill) como um valor constante fora de aes().
Uma maneira de contornar isso é definir color dentro de aes(), mas sem associá-lo a uma variável do conjunto de dados. Em vez disso, usamos valores de texto que serão tratados como categorias e aparecerão na legenda. Por exemplo:
Para definir as cores associadas a essas categorias, podemos usar a função scale_color_manual(), como visto anteriormente:
Campos geoquímicos
É comum ver pesquisadores definindo campos geoquímicos visualmente com a ajuda de softwares de edição gráfica.
O principal problema desse método é que a definição do campo não segue um critério estatístico e não é reprodutível. Diferentes pessoas podem traçar campos ligeiramente distintos a partir dos mesmos dados.
Uma alternativa em R é utilizar a função stat_peel() do pacote gggda, uma extensão do ggplot2.
A função stat_peel() cria envoltórias ao redor dos dados removendo, de forma iterativa, os pontos mais externos. Esse processo, conhecido como peeling, permite identificar regiões que concentram diferentes proporções dos dados.
Vamos usar stat_peel() para representar os morbs como um campo:
No código acima, utilizamos fill para definir o preenchimento do campo associado aos morbs. O argumento breaks = 0.95 indica que estamos representando a região que contém aproximadamente 95% das amostras. Além disso, definimos alpha = 0.7 para tornar o campo parcialmente transparente, facilitando a visualização dos pontos.
Bônus
O pacote plotly nos permite tornar um gráfico interativo com a função ggplotly(). Seu uso é bastante simples.
Primeiro, vamos salvar o gráfico que fizemos acima como meu_plot:
Em seguida, vamos aplicar a função ggplotly() usando meu_plot como argumento:
Como vimos acima, o plotly permite visualizar as concentrações dos óxidos passando o cursor sobre os pontos. Também é possível ativar ou desativar camadas do gráfico interagindo com a legenda.
Agora, vamos modificar meu_plot para que inclua o parâmetro text dentro de aes() no geom_point(). Vamos mapear text usando a variável sample_id. Que aviso é exibido quando executamos o código abaixo?
E o que acontece agora quando usamos a função ggplotly()?
Agora, o plotly exibe o nome das amostras quando passamos o cursor sobre os pontos. Isso é muito útil para identificar possíveis outliers, por exemplo.
Exportando gráficos
Para exportar gráficos, você pode usar a função ggsave(). Por padrão, essa função salva o último gráfico criado. Por exemplo:
ggsave("meu_plot.jpg")Para publicações, recomendo definir dpi = 300 e ajustar as dimensões da figura:
ggsave("meu_plot.tiff", dpi = 300, width = 8, height = 8)Se você quiser editar o gráfico posteriormente em um software de design gráfico, pode salvá-lo no formato .svg:
# SVG não requer dpi, pois é um formato vetorial (não raster)
ggsave("meu_plot.svg", width = 8, height = 8)Considerações finais
Na aula de hoje, introduzimos os principais conceitos do ggplot2, com foco na construção de scatterplots, que são um dos diagramas mais usados nas geociências. Na próxima aula, veremos como criar subplots com o ggplot2 e faremos uma breve exploração de outros tipos de gráficos que podemos construir.