Gramática dos gráficos: usando o plotnine no Python

A gramática dos gráficos descreve qualquer gráfico como a combinação de componentes independentes: dados, mapeamento, geometria, estatística, facetas, coordenadas e tema. Neste tutorial construímos um gráfico camada a camada com o plotnine no Python, usando as séries de IPCA e Selic do Banco Central.


A gramática dos gráficos é uma teoria que descreve qualquer gráfico estatístico como a combinação de componentes independentes: os dados, o mapeamento das variáveis, a forma geométrica, a transformação estatística, as facetas, as coordenadas e o tema. No Python, a biblioteca que implementa essa teoria é o plotnine, e com ela construímos um gráfico somando camadas em vez de escolher um modelo pronto de um catálogo.

Neste tutorial mostramos o que é cada componente dessa gramática, por que ela substitui com vantagem a lógica de catálogo das planilhas, e como as camadas se combinam na prática. O exemplo usa duas séries do Banco Central do Brasil, a taxa Selic e o IPCA, com 261 observações mensais entre dezembro de 2004 e agosto de 2026.

Gramática dos gráficos no plotnine: dispersão do IPCA em 12 meses contra a Selic anualizada, facetada por década, com reta de regressão em cada painel
Cada painel é uma década; a reta é uma regressão ajustada dentro do grupo. Fonte: Banco Central do Brasil (SGS).

Esse gráfico reúne cinco decisões independentes: os dados, o mapeamento dos eixos, a geometria de pontos, a reta ajustada por grupo e a divisão em painéis. Nas próximas seções separamos cada uma delas.

💡 Quer obter o código completo deste exercício, com o notebook pronto para rodar no Google Colab e os dados já tratados?

Obter o notebook completo →

O que é a gramática dos gráficos

Leland Wilkinson formalizou a gramática dos gráficos em The Grammar of Graphics, de 1999. A proposta do livro foi descrever qualquer gráfico estatístico como a combinação de um conjunto pequeno de componentes, em vez de tratá-los como tipos isolados.

A analogia com a língua explica o nome. Uma língua tem vocabulário finito e regras de combinação, e com isso produzimos um número ilimitado de frases. A gramática dos gráficos funciona do mesmo modo: em vez de uma lista fechada de gráficos prontos, ela oferece componentes que se combinam livremente.

A diferença prática aparece na comparação com a planilha. No Excel escolhemos um gráfico de um catálogo, e o que o catálogo não tem exige improviso. Na gramática dos gráficos não existe catálogo: descrevemos o gráfico pela combinação de componentes, e a figura resultante é consequência dessa descrição. O mesmo raciocínio vale para outras tarefas de análise, como mostramos ao simplificar análises de dados manuais do Excel usando o Python.

Os sete componentes

  • Dados: a tabela que alimenta a figura, com uma observação por linha e uma variável por coluna.
  • Mapeamento estético: a ligação entre uma coluna e uma propriedade visual, como a posição no eixo, a cor ou o tamanho.
  • Geometria: a forma que representa cada observação. Ponto, linha, barra e área são geometrias diferentes sobre os mesmos dados.
  • Transformação estatística: o cálculo feito antes de desenhar, como a contagem por faixa de um histograma ou uma reta de regressão.
  • Facetas: a divisão dos dados em painéis, repetindo o mesmo gráfico em cada recorte.
  • Coordenadas: como as posições viram lugar na tela. O cartesiano é o mais comum, e o polar transforma barras em fatias de pizza.
  • Tema: tudo o que não descreve dado, como fonte, cor de fundo, grade e posição da legenda.

A independência entre os componentes é o que dá poder à teoria. Trocar apenas a geometria converte uma dispersão em linha; trocar apenas as coordenadas converte barras em pizza. Nenhuma dessas mudanças exige refazer o gráfico do zero.

ggplot2 e plotnine: a mesma gramática em duas linguagens

Hadley Wickham implementou a teoria de Wilkinson no pacote ggplot2, da linguagem R, e foi essa implementação que popularizou a gramática na análise de dados. Já tratamos dela ao mostrar como visualizar dados com ggplot2.

No Python, as bibliotecas mais conhecidas de visualização seguem outra lógica. O matplotlib e o seaborn trabalham com comandos de desenho, e não com componentes de um gráfico, como mostramos no tutorial de visualização de dados com Matplotlib e Seaborn.

O plotnine traz a gramática dos gráficos para o Python, com sintaxe deliberadamente próxima à do ggplot2. Quem já escreve gráficos em R reaproveita quase tudo, e a diferença principal é que o plotnine pede parênteses em volta da expressão inteira.

Os dados do exemplo

Usamos duas séries do Sistema Gerenciador de Séries Temporais do Banco Central: o IPCA mensal, que é o índice oficial de inflação do país, e a taxa Selic acumulada no mês, que é a taxa básica de juros da economia. A coleta usa a biblioteca python-bcb, no mesmo espírito do que fazemos ao lidar com erros de coleta de dados do Banco Central.

Nenhuma das duas séries chega na unidade em que costumamos lê-las. A Selic vem como taxa do mês e o mercado a discute em termos anuais; o IPCA vem como variação do mês e a meta de inflação é definida sobre o acumulado de doze meses. A preparação converte as duas e acrescenta a coluna de década, que alimenta as facetas.

Mês IPCA 12 meses (%) Selic anualizada (% a.a.) Década
2026-03 4,14 15,53 2020s
2026-04 4,39 13,89 2020s
2026-05 4,72 13,62 2020s
2026-06 4,64 14,30 2020s
2026-07 4,44 15,66 2020s
2026-08 4,22 13,89 2020s

Cada linha é uma observação mensal, e é essa tabela que passamos ao plotnine. A estrutura importa: a gramática espera dados em formato longo, com uma observação por linha, e não a planilha larga em que cada coluna é um ano.

Construindo o gráfico camada a camada

Camada 1: dados e mapeamento

O gráfico começa com a função ggplot(), que recebe a tabela, e com a função aes(), que liga colunas a propriedades visuais. As camadas são somadas com o símbolo +, e a expressão inteira vai entre parênteses.

(
    ggplot(dados)                           # a tabela que alimenta o gráfico
    + aes(x="selic_anual", y="ipca_12m")    # Selic no eixo x, IPCA no eixo y
)
Primeira camada da gramática dos gráficos no plotnine: eixos escalados de Selic e IPCA sem nenhum ponto desenhado
Os eixos já estão escalados, mas nenhuma forma foi desenhada. Fonte: Banco Central do Brasil (SGS).

A figura sai com os eixos escalados e sem nenhum ponto. O plotnine já conhece o intervalo de cada variável e já reservou o espaço, e ainda não desenhou nada, porque não dissemos qual forma deve representar cada observação.

Esse resultado costuma parecer defeito na primeira vez, e é a demonstração de que mapeamento e geometria são decisões separadas. No Excel as duas viriam juntas na escolha do tipo de gráfico.

Camada 2: a geometria

A geometria diz qual forma representa cada linha da tabela. Como comparamos duas variáveis contínuas, cada mês vira um ponto, com geom_point().

(
    ggplot(dados)
    + aes(x="selic_anual", y="ipca_12m")
    + geom_point(color="#282f6b", alpha=.55, size=1.8)   # cada mês vira um ponto
)
Segunda camada da gramática dos gráficos no plotnine: os mesmos eixos agora com um ponto para cada mês da série de Selic e IPCA
A mesma figura anterior, agora com a geometria de pontos. Fonte: Banco Central do Brasil (SGS).

Os 261 meses da amostra aparecem. O argumento alpha controla a transparência, e isso importa porque muitos pontos se sobrepõem na região central: a transparência revela onde eles se acumulam.

A cor foi passada fora da função aes(), e essa distinção é o ponto mais confundido da gramática. Dentro do aes(), a cor vira função de uma coluna dos dados; fora dele, é uma constante aplicada a todos os pontos.

Camada 3: a cor como informação

Quando a cor entra dentro do aes(), ela deixa de ser decoração e passa a carregar informação. Mapeamos a década de cada observação.

(
    ggplot(dados)
    + aes(x="selic_anual", y="ipca_12m", color="decada")  # a cor agora é variável
    + geom_point(alpha=.6, size=1.8)
    + scale_color_manual(
        values=["#282f6b", "#1B998B", "#FF7A00"],
        name="Década"
    )
)
Terceira camada da gramática dos gráficos: pontos coloridos por década, com legenda gerada automaticamente pelo plotnine
A legenda nasce do mapeamento, sem ser pedida. Fonte: Banco Central do Brasil (SGS).

A legenda apareceu sozinha. Não a pedimos em nenhum momento: como a cor passou a representar uma variável, a gramática entende que o leitor precisa da chave de tradução entre cor e categoria.

A escala scale_color_manual() define quais cores correspondem a quais valores. Usamos a paleta da Análise Macro, com o azul-escuro na primeira posição.

Camada 4: estatística, facetas e tema

As três últimas camadas entram juntas. A transformação estatística ajusta uma reta de regressão por grupo, as facetas separam cada década em seu painel, e o tema cuida da aparência.

(
    ggplot(dados)
    + aes(x="selic_anual", y="ipca_12m", color="decada")
    + geom_point(alpha=.55, size=1.5)
    + stat_smooth(method="lm", se=False, size=1)   # a reta de regressão por grupo
    + facet_wrap("decada", nrow=1)                 # um painel por década
    + scale_color_manual(
        values=["#282f6b", "#1B998B", "#FF7A00"],
        guide=None                                 # a faceta já rotula
    )
    + labs(
        title="Juros e inflação caminham juntos, mas a relação muda a cada década",
        x="Selic anualizada (% a.a.)",
        y="IPCA acumulado em 12 meses (%)"
    )
    + theme_minimal(base_size=10)
)

A função stat_smooth() calcula uma regressão linear dentro de cada década e desenha a reta ajustada, com se=False suprimindo a faixa de erro-padrão. O cálculo acontece na hora de desenhar, e não exige criar colunas novas na tabela.

O facet_wrap() repete o mesmo gráfico para cada valor da coluna de década e mantém as escalas compartilhadas entre os painéis. A escala comum é o que torna os três painéis comparáveis entre si.

Na leitura do nosso exemplo, os anos 2000 e 2010 mostram retas inclinadas para cima, com juros mais altos convivendo com inflação mais alta. Nos anos 2020 a reta fica quase plana, e a nuvem se divide em duas regiões: juros baixos em 2020 e 2021, juros altos a partir de 2022.

A reta descreve associação entre as duas séries no período, e não relação de causa. Juros e inflação se determinam mutuamente ao longo do tempo, e separar esses efeitos exige um modelo que trate a simultaneidade, como discutimos ao investigar a causalidade entre a taxa Selic e as expectativas do Focus.

Trocando uma camada por vez

O ganho da gramática aparece quando queremos uma variação do gráfico. Para ver a inflação ao longo do tempo em vez de contra os juros, mudamos o mapeamento do eixo x e a geometria, e o restante permanece.

(
    ggplot(dados)
    + aes(x="data", y="ipca_12m")                 # o tempo entra no eixo x
    + geom_line(color="#282f6b", size=.7)         # a geometria vira linha
    + geom_hline(yintercept=3, linetype="dashed", # a meta como referência
                 color="#b22200", size=.6)
)

Duas alterações produziram um gráfico de natureza diferente, e a estrutura do código permaneceu. O geom_hline() acrescentou uma linha horizontal na meta de inflação, e as geometrias se acumulam: a série e a meta convivem na mesma figura porque cada uma é uma camada somada à anterior.

Essa é a mesma lógica que usamos na análise exploratória para modelagem preditiva no Python, quando precisamos gerar muitas visões dos mesmos dados em pouco tempo.

Aplicações no dia a dia

A gramática dos gráficos rende mais em contextos onde a mesma figura precisa ser refeita muitas vezes, com pequenas variações.

  • Relatórios recorrentes: o mesmo código gera o gráfico do mês seguinte quando o dado é atualizado, sem refazer a figura à mão.
  • Comparação entre recortes: as facetas produzem um painel por estado, setor ou faixa de renda a partir de uma linha de código, e mantêm as escalas comparáveis.
  • Padronização visual: o tema da instituição fica num objeto reutilizável, e todos os gráficos da equipe saem com a mesma identidade.
  • Exploração rápida: trocar a geometria custa uma palavra, o que permite testar várias representações dos mesmos dados antes de escolher.

O caso do relatório recorrente costuma ser o que mais pesa. Uma planilha exige refazer a seleção de intervalo e a formatação a cada atualização, e o código refaz o gráfico inteiro a partir do dado novo.

Considerações finais

Aprender a gramática dos gráficos muda menos a aparência das figuras e mais a forma de pensá-las. Em vez de procurar o gráfico certo num catálogo, passamos a descrever o que queremos mostrar, e o gráfico resulta dessa descrição.

O benefício varia conforme a área de atuação:

  • Analista de dados: a exploração fica mais rápida, porque testar uma representação nova custa a troca de uma camada.
  • Economista: os gráficos de conjuntura passam a se atualizar sozinhos quando a série nova é publicada.
  • Pesquisador: a figura do artigo fica reproduzível, e o revisor consegue refazer exatamente o mesmo gráfico.
  • Gestor e profissional de risco: o relatório periódico ganha padrão visual estável, sem retrabalho manual a cada rodada.
  • Quem trabalha em R e Python: a mesma gramática serve às duas linguagens, e o conhecimento transfere quase inteiro.

Quer construir análises como esta do zero?

Na formação Do Zero à Análise de Dados Econômicos e Financeiros usando Python e IA percorremos o caminho completo: coletar os dados nas fontes oficiais, tratá-los, analisá-los e apresentá-los em gráficos como os deste tutorial, sem pré-requisito de programação.

Conhecer a formação →

Se a intenção é acompanhar todas as trilhas da casa, o AM Black é a assinatura anual que dá acesso a todos os cursos.

Leia também

Referências

Wilkinson, L. (2005). The Grammar of Graphics. 2ª edição. Springer.

Wickham, H. (2010). A Layered Grammar of Graphics. Journal of Computational and Graphical Statistics, 19(1), 3-28.

Kibirige, H. (2024). Plotnine: A Grammar of Graphics for Python. Disponível em plotnine.org.

Compartilhe esse artigo

Facebook
Twitter
LinkedIn
WhatsApp
Telegram
Email
Print
Análise Macro © 2011 / 2026

comercial@analisemacro.com.br – Rua Visconde de Pirajá, 414, Sala 718
Ipanema, Rio de Janeiro – RJ – CEP: 22410-002

como podemos ajudar?

Preencha os seus dados abaixo e fale conosco no WhatsApp