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
- Fundamentos do Matplotlib: o sistema figure/axes/subplots, gráficos de linha, gráficos de barras e gráficos de dispersão
- Gráficos avançados do Seaborn: gráficos de distribuição (histplot), boxplots e mapas de calor
- Layouts com múltiplos subplots e personalização de estilo:
sns.set_theme, paletas de cores, configuração de fontes CJK - Visualização de dados de e-commerce na prática: tendências mensais de receita, participação por categoria, distribuição RFM de usuários
- Decisões de escolha de gráficos: escolhendo o melhor tipo de gráfico para seus dados
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.
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).
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
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:
# Executado com sucesso
(2) Tipos comuns de gráficos
▶ Exemplo: Gráfico de barras e gráfico de dispersão
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:
# 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
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:
# Executado com sucesso
(2) Mapas de calor
▶ Exemplo: Mapa de calor de correlação entre features
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:
# Executado com sucesso
(3) Layouts com múltiplos subplots
▶ Exemplo: Painel de análise de 4 dimensões do SalesPredict
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:
# Executado com sucesso
5. Personalização de estilo e escolha de gráficos
(1) Temas e paletas de cores do Seaborn
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
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
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:
# 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.svgou
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
hueno Seaborn? R:hueagrupa 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, ouplt.subplots_adjust(hspace=0.3, wspace=0.3)para controle manual do espaçamento.
📖 Resumo
- O sistema Figure/Axes do Matplotlib é a base de todos os gráficos: Figure é a tela, Axes é a área de plotagem
- O Seaborn oferece gráficos estatísticos de mais alto nível: histplot (distribuição KDE), boxplot (boxplot), heatmap (mapa de calor de correlação)
- Layouts com múltiplos subplots são criados com
plt.subplots(nrows, ncols)para gerenciamento unificado de vários gráficos - A escolha do gráfico segue o tipo de dado: tempo → linha, categoria → barra, distribuição → histograma, relação → dispersão/mapa de calor
- Exibição de CJK exige configuração de fonte, mas rótulos em inglês são recomendados para compatibilidade entre plataformas
seaborn.set_theme()define o estilo em uma linha; escolha paletas amigáveis para daltônicos quando possível
📝 Exercícios
- 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.
- 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]). - 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 eax.annotate()para adicionar anotações.
← Anterior: Processamento de Dados com Pandas | Próximo: Primeiros Passos com Scikit-learn →