Machine Learning: Visualização com Matplotlib e Seaborn

Última atualização: 2026-08-26

Um bom gráfico vale mais do que mil linhas de dados — a visualização é o primeiro passo para descobrir padrões.

1. O que você vai aprender


2. A história real de um gerente de produto

(1) O problema: tendências e anomalias são invisíveis em dados tabulares

O Bob enviou o relatório mensal de vendas do SalesPredict para a equipe — 50 linhas de dados em Excel, e ninguém conseguia dizer rapidamente qual categoria estava em declínio ou quais meses tinham flutuações anormais. As tendências dos dados dos EUA da Alice eram completamente diferentes das da China, mas olhar para números puros tornava quase impossível identificar a diferença. Os dados estavam enterrados em planilhas, e os insights-chave foram abafados.

(2) A solução com visualização

Um único gráfico de linha revelou instantaneamente uma tendência clara de queda na categoria Eletrônicos durante o Q3; um mapa de calor mostrou que a correlação entre gasto com anúncios e receita superava em muito as expectativas.

PYTHON
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd

# Visualização rápida revela padrões ocultos
df = pd.read_csv("monthly_sales.csv")
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
df.plot(x="month", y="revenue", ax=axes[0], title="Tendência de Receita")
sns.heatmap(df.corr(numeric_only=True), annot=True, ax=axes[1])
plt.tight_layout()
plt.savefig("sales_overview.png", dpi=150)

(3) O resultado: insights de negócio-chave em 5 minutos

Depois de substituir tabelas brutas por visualizações, o Bob identificou a queda de 15% na categoria Eletrônicos durante o Q3 em 5 minutos. Ele ajustou a estratégia de publicidade a tempo, recuperando cerca de 200 mil USD em perdas potenciais.


3. Fundamentos do Matplotlib

(1) O sistema Figure/Axes

O Matplotlib usa uma arquitetura em duas camadas: uma Figure (tela) contém um ou mais Axes (áreas de plotagem).

100%
graph TB
    FIG[Figure - Tela] --> AX1[Axes 1<br/>Subplot 1]
    FIG --> AX2[Axes 2<br/>Subplot 2]
    AX1 --> LINE[Gráfico de Linha]
    AX2 --> BAR[Gráfico de Barras]

▶ Exemplo: Criando um gráfico de linha básico

PYTHON
import matplotlib.pyplot as plt

# Dados de receita mensal (em mil USD)
months = ["Jan", "Fev", "Mar", "Abr", "Mai", "Jun",
          "Jul", "Ago", "Set", "Out", "Nov", "Dez"]
revenue = [120, 135, 150, 142, 160, 175, 180, 190, 195, 200, 220, 250]

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(months, revenue, marker="o", linewidth=2, color="#2196F3")
ax.set_title("Tendência de Receita Mensal", fontsize=14)
ax.set_xlabel("Mês")
ax.set_ylabel("Receita (mil USD)")
ax.grid(True, alpha=0.3)
ax.fill_between(months, revenue, alpha=0.1, color="#2196F3")

# Anotar o pico
peak_idx = revenue.index(max(revenue))
ax.annotate(f"Pico: {max(revenue)}k", xy=(peak_idx, max(revenue)),
            xytext=(peak_idx-2, max(revenue)+15),
            arrowprops=dict(arrowstyle="->", color="red"))

plt.tight_layout()
plt.savefig("revenue_trend.png", dpi=150)

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

(2) Tipos comuns de gráficos

▶ Exemplo: Gráfico de barras e gráfico de dispersão

PYTHON
import matplotlib.pyplot as plt
import numpy as np

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Gráfico de barras: receita por categoria
categories = ["Eletrônicos", "Roupas", "Alimentos", "Livros", "Casa"]
revenue = [2500, 1450, 900, 700, 4000]
colors = ["#FF6384", "#36A2EB", "#FFCE56", "#4BC0C0", "#9966FF"]

axes[0].barh(categories, revenue, color=colors)
axes[0].set_title("Receita por Categoria")
axes[0].set_xlabel("Receita (mil USD)")

# Gráfico de dispersão: gasto com anúncios vs receita
np.random.seed(42)
ad_spend = np.random.uniform(10, 100, 50)
sales = 50 + 0.8 * ad_spend + np.random.normal(0, 10, 50)

axes[1].scatter(ad_spend, sales, alpha=0.6, color="#2196F3", edgecolors="white")
axes[1].set_title("Gasto com Anúncios vs Receita")
axes[1].set_xlabel("Gasto com Anúncios (mil USD)")
axes[1].set_ylabel("Receita (mil USD)")

# Adicionar linha de tendência
z = np.polyfit(ad_spend, sales, 1)
p = np.poly1d(z)
axes[1].plot(ad_spend, p(ad_spend), "r--", alpha=0.8, linewidth=2)

plt.tight_layout()
plt.savefig("bar_scatter.png", dpi=150)

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso
Tipo de gráfico Melhor caso de uso Função do Matplotlib
Gráfico de linha Tendências no tempo ax.plot()
Gráfico de barras Comparação entre categorias ax.bar() / ax.barh()
Gráfico de dispersão Relação entre duas variáveis ax.scatter()
Gráfico de pizza Distribuição proporcional ax.pie()
Histograma Distribuição de uma variável ax.hist()

4. Gráficos avançados do Seaborn

O Seaborn é construído sobre o Matplotlib, oferecendo gráficos estatísticos de mais alto nível e estilos padrão mais polidos.

(1) Gráficos de distribuição

▶ Exemplo: Análise da distribuição do valor dos pedidos

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np

# Gerar dados de valor de pedido
rng = np.random.default_rng(42)
orders_normal = rng.normal(150, 50, 1000)
orders_normal = orders_normal[orders_normal > 0]  # Remover negativos

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

# Histograma com KDE
sns.histplot(orders_normal, bins=30, kde=True, ax=axes[0], color="#2196F3")
axes[0].set_title("Distribuição do Valor dos Pedidos")
axes[0].set_xlabel("Valor (USD)")

# Boxplot por categoria
categories = rng.choice(["Eletrônicos", "Roupas", "Alimentos"], 500)
amounts = np.where(categories == "Eletrônicos",
                   rng.normal(300, 80, 500),
                   np.where(categories == "Roupas",
                            rng.normal(120, 40, 500),
                            rng.normal(50, 20, 500)))
amounts = np.clip(amounts, 1, None)
data = {"category": categories, "amount": amounts}

sns.boxplot(data=data, x="category", y="amount", ax=axes[1], palette="Set2")
axes[1].set_title("Valor dos Pedidos por Categoria")

plt.tight_layout()
plt.savefig("distribution.png", dpi=150)

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

(2) Mapas de calor

▶ Exemplo: Mapa de calor de correlação entre features

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# Simular correlações de features do SalesPredict
np.random.seed(42)
n = 200
ad_spend = np.random.uniform(10, 100, n)
traffic = ad_spend * 1.2 + np.random.normal(0, 15, n)
conversion = traffic * 0.03 + np.random.normal(0, 0.5, n)
revenue = conversion * 150 + np.random.normal(0, 500, n)
customer_age = np.random.uniform(18, 65, n)

df = pd.DataFrame({
    "ad_spend": ad_spend,
    "traffic": traffic,
    "conversion_rate": conversion,
    "revenue": revenue,
    "customer_age": customer_age,
})

corr = df.corr()

fig, ax = plt.subplots(figsize=(8, 6))
sns.heatmap(corr, annot=True, fmt=".2f", cmap="RdBu_r",
            center=0, vmin=-1, vmax=1, ax=ax,
            square=True, linewidths=0.5)
ax.set_title("Mapa de Calor de Correlação entre Features")
plt.tight_layout()
plt.savefig("correlation_heatmap.png", dpi=150)

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

(3) Layouts com múltiplos subplots

▶ Exemplo: Painel de análise de 4 dimensões do SalesPredict

PYTHON
import seaborn as sns
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

rng = np.random.default_rng(42)
df = pd.DataFrame({
    "date": pd.date_range("2024-01-01", periods=90),
    "revenue": rng.normal(5000, 1000, 90).cumsum(),
    "category": rng.choice(["Elec", "Roupa", "Alim"], 90),
    "orders": rng.integers(50, 200, 90),
})

fig, axes = plt.subplots(2, 2, figsize=(14, 10))

# (1) Tendência de receita
axes[0, 0].plot(df["date"], df["revenue"], color="#2196F3")
axes[0, 0].set_title("Tendência Diária de Receita")

# (2) Distribuição por categoria
cat_rev = df.groupby("category")["revenue"].sum()
axes[0, 1].pie(cat_rev, labels=cat_rev.index, autopct="%1.1f%%")

# (3) Distribuição de pedidos
sns.histplot(df["orders"], bins=20, kde=True, ax=axes[1, 0], color="#4CAF50")
axes[1, 0].set_title("Distribuição de Pedidos")

# (4) Receita vs Pedidos
axes[1, 1].scatter(df["orders"], df["revenue"], alpha=0.5, c="#FF5722")
axes[1, 1].set_title("Receita vs Pedidos")

plt.tight_layout()
plt.savefig("dashboard.png", dpi=150)

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

5. Personalização de estilo e escolha de gráficos

(1) Temas e paletas de cores do Seaborn

PYTHON
import seaborn as sns

# Definir tema global
sns.set_theme(style="whitegrid", palette="muted", font_scale=1.2)

# Temas disponíveis: darkgrid, whitegrid, dark, white, ticks
# Paletas disponíveis: deep, muted, pastel, bright, dark, colorblind
Tema Fundo Grade Melhor para
darkgrid Escuro Sim Visualizações com muitos dados
whitegrid Branco Sim Relatórios acadêmicos
dark Escuro Não Apresentações
white Branco Não Artigos
ticks Branco Não Estilo minimalista

(2) Guia de decisão para escolha de gráfico

100%
graph TB
    DATA[Tipo de Dado] --> CAT[Categórico]
    DATA --> NUM[Numérico]
    DATA --> TIME[Série Temporal]
    CAT --> COMP[Comparação<br/>Gráfico de Barras]
    CAT --> PART[Parte do Todo<br/>Pizza / Barras Empilhadas]
    NUM --> DIST[Distribuição<br/>Histograma / KDE / Box]
    NUM --> REL[Relação<br/>Dispersão / Mapa de Calor]
    TIME --> TREND[Tendência<br/>Gráfico de Linha]
    TIME --> SEA[Sazonalidade<br/>Gráfico Sazonal]

▶ Exemplo: Configuração de fonte CJK

PYTHON
import matplotlib.pyplot as plt

# Método 1: Usar fonte SimHei (Windows)
plt.rcParams["font.sans-serif"] = ["SimHei", "Microsoft YaHei"]
plt.rcParams["axes.unicode_minus"] = False

# Método 2: Usar rótulos em inglês (recomendado para i18n)
# Mantenha todos os rótulos em inglês para evitar problemas de fonte entre plataformas
fig, ax = plt.subplots()
ax.set_title("Monthly Sales Report")  # Inglês para compatibilidade
ax.set_xlabel("Month")
ax.set_ylabel("Revenue (thousand USD)")

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

❓ Perguntas Frequentes

P: Devo usar Matplotlib ou Seaborn? R: Use Seaborn para análises do dia a dia (mais limpo e elegante), e Matplotlib quando precisar de controle refinado. O Seaborn é construído sobre o Matplotlib, então você pode misturar e combinar livremente.

P: Como corrijo caracteres CJK bagunçados nos gráficos? R: Defina plt.rcParams["font.sans-serif"] para uma fonte CJK. Porém, é recomendado usar rótulos em inglês para evitar problemas de fonte entre plataformas.

P: Minhas figuras salvas ficam borradas. Como corrigir? R: Defina o parâmetro dpi: plt.savefig("fig.png", dpi=150). Use 300+ para artigos, 100-150 para web. Para gráficos vetoriais, use o formato .svg ou .pdf.

P: Como escolher o tipo certo de gráfico? R: Depende do tipo de dado e do objetivo — use gráficos de linha para tendências no tempo, gráficos de barras para comparar categorias, histogramas/boxplots para distribuições, e gráficos de dispersão/mapas de calor para relações entre duas variáveis.

P: O que faz o parâmetro hue no Seaborn? R: hue agrupa e colore os dados pela coluna especificada. Por exemplo, sns.scatterplot(data=df, x="ad_spend", y="revenue", hue="category") atribui uma cor diferente a cada categoria.

P: Como corrijo subplots com espaçamento apertado demais? R: Use plt.tight_layout() para ajuste automático, ou plt.subplots_adjust(hspace=0.3, wspace=0.3) para controle manual do espaçamento.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Use o Matplotlib para desenhar um gráfico de linha mostrando 12 meses de tendências de vendas. Adicione título e rótulos aos eixos. Dica: consulte o exemplo de gráfico de linha na Seção 3.
  2. Intermediário (Dificuldade ⭐⭐): Use Seaborn para criar um painel de subplots 2x2: gráfico de linha (tendência), gráfico de barras (comparação de categorias), boxplot (distribuição) e mapa de calor (correlação), usando dados simulados do SalesPredict. Dica: plt.subplots(2,2) + sns.xxx(ax=axes[i,j]).
  3. Desafio (Dificuldade ⭐⭐⭐): Crie um conceito de dashboard interativo — plote um gráfico de tendência de receita mensal, destaque "meses de promoção" e "meses regulares" em cores diferentes, e adicione anotações explicando os efeitos das promoções. Dica: use ax.axvspan() para sombrear regiões e ax.annotate() para adicionar anotações.

← Anterior: Processamento de Dados com Pandas | Próximo: Primeiros Passos com Scikit-learn →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%