quem quer gramática de gráficos idiomática em Julia
Makie.jl puro
controle total sobre a figura
Este capítulo mostra os três sobre o mesmo conjunto de dados, porque a escolha certa depende da tarefa — e porque saber traduzir entre eles evita ficar preso.
Uma figura não pode ser verificada automaticamente; por isso, na maioria dos quadros Sua vez, você compara o seu gráfico com o da solução. Comece cada sessão carregando os pacotes e os dados, com a pasta do livro aberta no VS Code:
usingTidierPlotsggplot(ponds_c, @aes(x = canopy, y = richness, color = region)) +geom_point(alpha =0.7) +labs(x ="Cobertura de dossel (%)", y ="Riqueza de espécies", title ="Riqueza declina com o sombreamento")
Figura 6.1: Riqueza em função da cobertura de dossel, por região.
Em R
ggplot(ponds_c, aes(x = canopy, y = richness, colour = region)) +geom_point(alpha =0.7) +labs(x ="Canopy cover (%)", y ="Species richness")
A tradução é quase caractere a caractere; a diferença é o @ em @aes.
NotaSua vez 6.1 — Riqueza e temperatura
Refaça a Figura 6.1 com a temperatura da água (temp_c) no eixo x e os pontos coloridos pelo hidroperíodo (hydro). Dê nome aos dois eixos. A riqueza muda com a temperatura tão claramente quanto com o dossel?
Este não tem verificador: compare a sua figura com a da solução.
DicaDica
Só mudam o mapeamento em @aes e os rótulos.
CuidadoSolução
ggplot(ponds_c, @aes(x = temp_c, y = richness, color = hydro)) +geom_point(alpha =0.7) +labs(x ="Temperatura da água (°C)", y ="Riqueza de espécies")
A nuvem é bem mais achatada que a do dossel. A simulação inclui um efeito da temperatura (scripts/make_data.jl), mas pequeno: cerca de 3% a mais de espécies por grau, invisível diante da variação entre lagoas.
6.2AlgebraOfGraphics.jl: gramática algébrica
AoG trata gráficos como uma álgebra: * combina camadas, + as sobrepõe.
plt = AlgebraOfGraphics.data(ponds_c) *mapping(:canopy =>"Cobertura de dossel (%)",:richness =>"Riqueza de espécies", color =:region =>"Região") * (visual(Scatter, alpha =0.6) + AlgebraOfGraphics.linear())draw(plt; figure = (size = (700, 450),))
Figura 6.2: O mesmo gráfico em AlgebraOfGraphics, com ajuste linear por região.
Nota
AlgebraOfGraphics.data e AlgebraOfGraphics.linear são qualificados porque os nomes data e linear colidem com outros pacotes carregados. Em um script que use só AoG, data(...) e linear() bastam.
NotaSua vez 6.2 — Tamanho corporal, com retas ajustadas
Com AlgebraOfGraphics, faça o gráfico de body_size contra temp_c, colorido por hydro, com um ajuste linear para cada hidroperíodo. Lagoas permanentes e temporárias diferem?
Este não tem verificador: compare a sua figura com a da solução.
DicaDica
Parta do bloco acima e mude o mapping. As retas ajustadas seguem automaticamente o agrupamento por cor.
CuidadoSolução
plt = AlgebraOfGraphics.data(ponds_c) *mapping(:temp_c =>"Temperatura da água (°C)",:body_size =>"Tamanho corporal (mm)", color =:hydro =>"Hidroperíodo") * (visual(Scatter, alpha =0.6) + AlgebraOfGraphics.linear())draw(plt; figure = (size = (700, 450),))
As duas retas quase coincidem: na simulação, o tamanho corporal depende da temperatura e do dossel, mas não do hidroperíodo. Testamos isso formalmente no Capítulo 8.
Figura 6.3: Relação riqueza–área facetada por hidroperíodo.
NotaSua vez 6.3 — Facetas na gramática do ggplot
Traduza a Figura 6.3 para TidierPlots.jl, usando facet_wrap para separar os painéis por hidroperíodo. Deixe de fora as retas ajustadas (veja o aviso na solução).
Este não tem verificador: compare a sua figura com a da solução.
DicaDica
facet_wrap(facets = :hydro) é adicionado com +, como qualquer outra camada.
CuidadoSolução
ggplot(ponds_c, @aes(x = log_area, y = richness, color = region)) +geom_point(alpha =0.6) +facet_wrap(facets =:hydro) +labs(x ="log(área)", y ="Riqueza")
AvisoUm limite do TidierPlots
No TidierPlots.jl 1.0.0 (conferido em setembro de 2026), adicionar geom_smooth(method = "lm") a um gráfico com facetas falha com column name :facet not found. geom_smooth funciona sem facetas, e facetas funcionam sem geom_smooth, mas não os dois juntos. Quando a gramática do ggplot chega a um limite como este, o AlgebraOfGraphics (Figura 6.3) é a saída.
Quando a figura precisa de um layout que a gramática não expressa, desça ao Makie.
fig =Figure(size = (860, 380))ax1 =Axis(fig[1, 1], xlabel ="Cobertura de dossel (%)", ylabel ="Riqueza", title ="(a) Dossel")scatter!(ax1, ponds_c.canopy, ponds_c.richness, color = (:steelblue, 0.6))ax2 =Axis(fig[1, 2], xlabel ="log(área)", ylabel ="Riqueza", title ="(b) Área")scatter!(ax2, ponds_c.log_area, ponds_c.richness, color = (:darkorange, 0.6))ax3 =Axis(fig[1, 3], xlabel ="Riqueza", ylabel ="Frequência", title ="(c) Distribuição")hist!(ax3, ponds_c.richness, bins =12, color = (:seagreen, 0.7))fig
Figura 6.5: Figura composta montada manualmente com Makie.
O sistema de layout do Makie é baseado em grade (fig[linha, coluna]), cobrindo o papel de patchwork e cowplot no R sem pacote adicional.
NotaSua vez 6.5 — Dois painéis à mão
Monte uma figura com size = (800, 350) e dois painéis: à esquerda, um boxplot da riqueza por região; à direita, um gráfico de barras com a proporção de lagoas com a espécie-foco em cada região (os números do 5.4). Guarde-a em fig_regioes.
Este não tem verificador: compare a sua figura com a da solução.
DicaDica
boxplot! e barplot! do Makie querem números no eixo x. Dê um número a cada região com [findfirst(==(r), regs) for r in ponds.region], onde regs = ["Amazon", "Atlantic", "Cerrado"], e recoloque os nomes com xticks = (1:3, regs) em cada Axis.
CuidadoSolução
regs = ["Amazon", "Atlantic", "Cerrado"]idx = [findfirst(==(r), regs) for r in ponds.region]props = [mean(ponds.focal[ponds.region .== r]) for r in regs]fig_regioes =Figure(size = (800, 350))ax1 =Axis(fig_regioes[1, 1], xticks = (1:3, regs), xlabel ="Região", ylabel ="Riqueza", title ="(a) Riqueza")boxplot!(ax1, idx, ponds.richness, color = (:steelblue, 0.6))ax2 =Axis(fig_regioes[1, 2], xticks = (1:3, regs), xlabel ="Região", ylabel ="Proporção de lagoas", title ="(b) Espécie-foco")barplot!(ax2, 1:3, props, color = (:darkorange, 0.8))fig_regioes
Os dois painéis contam histórias diferentes: a riqueza varia muito entre regiões; a ocorrência da espécie-foco, quase nada.
6.6 Salvando figuras
save("figura.png", fig; px_per_unit =3) # raster em alta resoluçãosave("figura.pdf", fig) # vetorial, para publicaçãosave("figura.svg", fig)
NotaSua vez 6.6 — Uma figura para publicação
Salve a fig_regioes do 6.5 como focal-by-region.png, com três pixels por unidade, na pasta do livro. Depois verifique o arquivo: checar("6.6", "focal-by-region.png").
DicaDica
O bloco acima mostra o argumento que define a resolução.
Uma figura de 800 × 350 com três pixels por unidade gera uma imagem de 2400 × 1050 px — suficiente para uma figura de duas colunas em um periódico. Para saída vetorial, salve em .pdf.
DicaEscolhendo o backend
CairoMakie gera saída estática de qualidade de publicação (PNG, PDF, SVG) e é o que este livro usa. GLMakie abre janelas interativas com aceleração de GPU — útil para explorar dados, inadequado para gerar um livro.
Desafios
No 6.1 você julgou o efeito da temperatura a olho. Adicione um ajuste linear por hidroperíodo com geom_smooth(method = "lm"). A reta muda a sua leitura do gráfico? O que você precisaria saber antes de confiar nela?
O painel (b) do 6.5 mostra proporções sem incerteza. Adicione a cada barra uma barra de erro de \(\pm 2\) erros-padrão, com \(\text{EP} = \sqrt{p(1-p)/n}\) e errorbars!. As regiões ainda parecem diferentes?
Refaça a Figura 6.5 com uma cor por região em todos os painéis e uma única legenda compartilhada à direita (Legend(fig[1, 4], ...)).
Danisch, Simon, e Julius Krumbiegel. 2021. «Makie.jl: Flexible high-performance data visualization for Julia». Journal of Open Source Software 6 (65): 3349. https://doi.org/10.21105/joss.03349.