Resposta rápida
Seaborn é a biblioteca de gráficos estatísticos do Python, construída sobre o Matplotlib. Você passa um DataFrame e o nome das colunas: sns.histplot(data=df, x="coluna"). Ela cuida de cores, legenda e estatísticas (médias, densidade, intervalos de confiança).
1
2
3
4
5
6
import matplotlib.pyplot as plt
import seaborn as sns
gorjetas = sns.load_dataset("tips") # dataset de exemplo (244 linhas)
sns.scatterplot(data=gorjetas, x="total_bill", y="tip", hue="time")
plt.show() # pontos coloridos por almoço/jantar
Resumo em 30 segundos:
- Distribuição:
histplot,kdeplot. Relação:scatterplot,lineplot. Categorias:countplot,barplot,boxplot,violinplot. -
hue="coluna"colore por categoria e cria a legenda sozinho. -
displot,relplotecatplotsão figure-level: dividem em painéis comcol=. - Heatmap de correlação:
sns.heatmap(df.corr(numeric_only=True), annot=True). - Ajustes finos (títulos, eixos, tamanho) continuam sendo feitos com Matplotlib.
Salve salve Pythonista!
Você já sabe criar gráficos com Matplotlib, mas cansou de escrever dez linhas para fazer um boxplot por categoria com legenda decente? É aí que entra o Seaborn: ele entende DataFrames, agrupa os dados por você e calcula as estatísticas que o gráfico precisa, tudo em uma chamada.
Neste guia você vai ver os quatro grupos de gráficos que resolvem quase toda análise exploratória (distribuição, relação, categóricos e heatmap de correlação), a diferença entre funções axes-level e figure-level, e como personalizar e salvar. No final: tabela de decisão, erros comuns e exercícios resolvidos.
Todos os exemplos foram executados com seaborn 0.13.2 (a versão mais recente em setembro de 2026), matplotlib 3.10, pandas 2.3 e Python 3.10. Como os gráficos não aparecem aqui como imagem, cada exemplo traz o código completo e uma descrição do que você vai ver ao executá-lo.
Então… Bora pro post! ![]()
Vá Direto ao Assunto…
- O que é o Seaborn e quando usar
- Instalação e primeiro gráfico
- Funções axes-level e figure-level
- Gráficos de distribuição: histplot, kdeplot e displot
- Gráficos de relação: scatterplot, lineplot e lmplot
- Gráficos categóricos: countplot, barplot, boxplot e violinplot
- Heatmap de correlação com Seaborn
- Como personalizar e salvar gráficos do Seaborn
- Qual gráfico do Seaborn usar
- Erros comuns
- Exercícios resolvidos
O que é o Seaborn e quando usar
O Seaborn é uma biblioteca de visualização estatística criada por Michael Waskom. Ele não substitui o Matplotlib: usa o Matplotlib por baixo e acrescenta uma camada que conversa com o pandas.
Para um boxplot do valor da conta por dia da semana, no Matplotlib puro você separa os dados de cada dia em listas e configura os rótulos. No Seaborn:
1
sns.boxplot(data=gorjetas, x="day", y="total_bill")
Ele agrupa, ordena as categorias, rotula os eixos e aplica o estilo. Use o Seaborn quando os dados estão num DataFrame e você quer explorar (distribuições, comparação entre grupos, correlações) com estatística embutida. Continue no Matplotlib puro para gráficos muito customizados ou animações. Se precisa revisar a base, veja o post sobre como criar gráficos com Matplotlib, e para a estrutura de dados que o Seaborn consome, o post sobre DataFrames do pandas.
Instalação e primeiro gráfico
Instale num ambiente virtual. O pip traz junto as dependências obrigatórias (numpy, pandas e matplotlib):
1
pip install seaborn
O Seaborn vem com vários datasets de exemplo, carregados com sns.load_dataset(). Neste post vamos usar três: tips (contas e gorjetas de um restaurante), flights (passageiros de avião por mês, de 1949 a 1960) e penguins (medidas de pinguins de três espécies).
1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme() # estilo padrão do seaborn (fundo cinza com grade)
gorjetas = sns.load_dataset("tips")
print(gorjetas.head())
print(gorjetas.shape)
ax = sns.scatterplot(data=gorjetas, x="total_bill", y="tip", hue="time")
ax.set(xlabel="Valor da conta (US$)", ylabel="Gorjeta (US$)", title="Conta x gorjeta")
plt.show()
Saída no terminal:
1
2
3
4
5
6
7
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4
(244, 7)
O que o gráfico mostra: uma nuvem de 244 pontos, com o valor da conta no eixo X (de 3 a 51 dólares) e a gorjeta no eixo Y (de 1 a 10 dólares). A nuvem sobe da esquerda para a direita: contas maiores tendem a ter gorjetas maiores. Os pontos azuis (almoço) se concentram nas contas abaixo de 25 dólares, e os laranja (jantar) se espalham por toda a faixa. A legenda “time” foi criada sozinha pelo hue.
O padrão se repete no post inteiro: data= recebe o DataFrame e x=, y= e hue= recebem nomes de colunas. A função devolve um Axes do Matplotlib, ajustado com ax.set().
Sem internet? O load_dataset() baixa o CSV do repositório seaborn-data no GitHub na primeira vez e guarda em cache em ~/seaborn-data. Se estiver offline, gere um DataFrame parecido no próprio código:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import numpy as np
import pandas as pd
import seaborn as sns
try:
gorjetas = sns.load_dataset("tips")
except Exception as erro: # sem internet: gera dados parecidos
print("Sem acesso ao dataset:", type(erro).__name__)
rng = np.random.default_rng(42)
total = rng.uniform(5, 50, 244).round(2)
gorjetas = pd.DataFrame({
"total_bill": total,
"tip": (total * rng.uniform(0.10, 0.20, 244)).round(2),
"day": rng.choice(["Thur", "Fri", "Sat", "Sun"], 244),
"time": rng.choice(["Lunch", "Dinner"], 244),
})
print(gorjetas.shape)
Saída offline (simulada bloqueando a rede):
1
2
Sem acesso ao dataset: URLError
(244, 4)
Com dados próprios, o caminho normal é ler um arquivo com pd.read_csv(), como mostramos no post sobre importar CSV no pandas.
Funções axes-level e figure-level
Antes dos gráficos, um conceito que evita muita dor de cabeça. O Seaborn organiza as funções em três famílias, e cada família tem uma função figure-level e várias axes-level (visão geral na documentação):
| Família | Figure-level | Axes-level |
|---|---|---|
| Relação | relplot |
scatterplot, lineplot
|
| Distribuição | displot |
histplot, kdeplot, ecdfplot, rugplot
|
| Categóricos | catplot |
countplot, barplot, boxplot, violinplot, stripplot, swarmplot, pointplot
|
-
Axes-level desenha num único eixo (
Axes) do Matplotlib, aceitaax=para ir num subplot específico e devolve oAxes. Tamanho:plt.subplots(figsize=(largura, altura)). -
Figure-level cria a figura inteira, divide em painéis com
col=erow=e devolve umFacetGrid. Tamanho:height=easpect=. Não aceitaax=.
Guarde isso: ax.set_title() funciona no retorno de histplot, mas não no de displot. Voltaremos a esse ponto nos erros comuns.
Gráficos de distribuição: histplot, kdeplot e displot
Gráficos de distribuição respondem “como os valores de uma coluna se espalham?”. Comece pelos números:
1
2
3
4
5
6
7
8
9
10
11
12
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style="whitegrid")
gorjetas = sns.load_dataset("tips")
print(gorjetas["total_bill"].describe().round(2))
ax = sns.histplot(data=gorjetas, x="total_bill", bins=20, kde=True)
ax.set(xlabel="Valor da conta (US$)", ylabel="Quantidade de mesas")
print(len(ax.patches), "barras")
plt.show()
Saída:
1
2
3
4
5
6
7
8
9
10
count 244.00
mean 19.79
std 8.90
min 3.07
25% 13.35
50% 17.80
75% 24.13
max 50.81
Name: total_bill, dtype: float64
20 barras
O que o gráfico mostra: um histograma com 20 barras entre 3 e 51 dólares. A barra mais alta fica perto de 16 dólares (37 mesas) e, a partir daí, as barras vão diminuindo para a direita, formando uma “cauda” longa até 50 dólares. O kde=True desenha por cima uma curva suave de densidade que acompanha esse formato. É uma distribuição assimétrica à direita, e por isso a média (19,79) é maior que a mediana (17,80).
Para comparar a distribuição entre grupos, o kdeplot com hue sobrepõe uma curva por categoria:
1
2
3
4
sns.kdeplot(data=gorjetas, x="total_bill", hue="time", fill=True, common_norm=False)
plt.show()
print(gorjetas.groupby("time", observed=True)["total_bill"].median())
Saída:
1
2
3
4
time
Lunch 15.965
Dinner 18.390
Name: total_bill, dtype: float64
O que o gráfico mostra: duas curvas preenchidas. A do almoço é mais alta e estreita, com pico perto de 14 dólares; a do jantar é mais larga, com pico perto de 17 e cauda mais longa. O common_norm=False dá área 1 a cada curva, para comparar formatos entre grupos de tamanhos diferentes (68 almoços e 176 jantares). A curva começa um pouco abaixo de zero porque a KDE suaviza os dados; cut=0 corta isso.
Para ver os grupos lado a lado em vez de sobrepostos, use a versão figure-level, displot, com col=:
1
2
3
4
g = sns.displot(data=gorjetas, x="total_bill", col="time", bins=15, height=3.5)
g.set_axis_labels("Valor da conta (US$)", "Mesas")
plt.show()
print(type(g).__name__, g.axes.shape)
Saída:
1
FacetGrid (1, 2)
O que o gráfico mostra: dois histogramas lado a lado (“time = Lunch” e “time = Dinner”) com o mesmo eixo Y, deixando evidente que há muito mais jantares.
Está curtindo esse conteúdo? ![]()
Que tal receber 30 dias de conteúdo direto na sua Caixa de Entrada?
Gráficos de relação: scatterplot, lineplot e lmplot
Gráficos de relação mostram como duas variáveis numéricas se comportam juntas. O scatterplot você já viu no primeiro exemplo; além de hue, ele aceita style (formato do marcador) e size (tamanho do ponto) para codificar mais colunas.
Com dados em sequência (tempo), use lineplot. Atenção a um comportamento automático: se houver vários valores de Y para o mesmo X, o Seaborn agrega (calcula a média) e desenha uma faixa de intervalo de confiança de 95%:
1
2
3
4
5
6
voos = sns.load_dataset("flights")
print(voos.head(3))
print(voos.groupby("year")["passengers"].sum().iloc[[0, -1]])
sns.lineplot(data=voos, x="year", y="passengers")
plt.show()
Saída:
1
2
3
4
5
6
7
8
year month passengers
0 1949 Jan 112
1 1949 Feb 118
2 1949 Mar 132
year
1949 1520
1960 5714
Name: passengers, dtype: int64
O que o gráfico mostra: uma linha subindo de cerca de 127 passageiros (média mensal de 1949: 1520 / 12) para cerca de 476 em 1960, com uma faixa clara em volta, o intervalo de confiança da média dos 12 meses, que alarga com os anos. Para uma linha por mês, passe hue="month"; para tirar a faixa, errorbar=None.
Para ver a tendência com uma reta de regressão, use lmplot (figure-level) ou regplot (axes-level):
1
2
3
4
5
6
7
8
9
import numpy as np
sns.lmplot(data=gorjetas, x="total_bill", y="tip", hue="smoker", height=4)
plt.show()
print(gorjetas[["total_bill", "tip"]].corr().round(2))
for fumante, grupo in gorjetas.groupby("smoker", observed=True):
inclinacao = np.polyfit(grupo["total_bill"], grupo["tip"], 1)[0]
print(fumante, round(inclinacao, 3))
Saída:
1
2
3
4
5
total_bill tip
total_bill 1.00 0.68
tip 0.68 1.00
Yes 0.07
No 0.137
O que o gráfico mostra: a nuvem de pontos com duas retas, uma azul (fumantes) e uma laranja (não fumantes), cada uma com uma faixa sombreada de incerteza. A reta laranja é mais inclinada: entre não fumantes, a gorjeta cresce cerca de 0,137 dólar por dólar de conta, contra 0,070 entre fumantes (valores calculados com np.polyfit). A correlação geral entre conta e gorjeta é 0,68.
Gráficos categóricos: countplot, barplot, boxplot e violinplot
Quando o eixo X é uma categoria (dia, turno, espécie), você está no território dos gráficos categóricos. A coluna day do dataset é do tipo categórico do pandas, com a ordem ['Thur', 'Fri', 'Sat', 'Sun'], e o Seaborn respeita essa ordem.
countplot conta quantas linhas há em cada categoria:
1
2
3
ax = sns.countplot(data=gorjetas, x="day")
print([int(barra.get_height()) for barra in ax.patches])
plt.show()
Saída: [62, 19, 87, 76]
O que o gráfico mostra: quatro barras, na ordem quinta, sexta, sábado e domingo. Sábado é a mais alta (87 mesas) e sexta a mais baixa (19).
barplot mostra uma estatística (a média, por padrão) de uma coluna numérica por categoria, com uma barra de erro:
1
2
3
ax = sns.barplot(data=gorjetas, x="day", y="total_bill", errorbar="sd")
print([round(float(barra.get_height()), 2) for barra in ax.patches])
plt.show()
Saída: [17.68, 17.15, 20.44, 21.41]
O que o gráfico mostra: a média da conta por dia, crescendo no fim de semana (domingo é o maior, 21,41). O errorbar="sd" desenha uma linha preta vertical no topo de cada barra com mais ou menos um desvio padrão; o padrão seria o intervalo de confiança de 95% (errorbar=("ci", 95)). Para usar a mediana no lugar da média, passe estimator="median".
A média esconde muita coisa. O boxplot mostra a distribuição inteira de cada grupo: mediana, quartis e outliers.
1
2
3
4
sns.boxplot(data=gorjetas, x="day", y="total_bill", hue="smoker")
plt.show()
print(gorjetas.groupby("day", observed=True)["total_bill"].median())
Saída:
1
2
3
4
5
6
day
Thur 16.20
Fri 15.38
Sat 18.24
Sun 19.63
Name: total_bill, dtype: float64
O que o gráfico mostra: duas caixas por dia (azul para fumantes, laranja para não fumantes). A linha no meio é a mediana, as bordas são o 1º e o 3º quartis, os “bigodes” vão até 1,5 vez a altura da caixa e os círculos soltos são outliers (contas de 40 a 50 dólares). No fim de semana, as caixas dos fumantes são bem mais altas: os valores variam mais.
O violinplot tem a mesma sintaxe, mas troca a caixa por uma curva de densidade espelhada, mais larga onde os valores se concentram (você vai usá-lo no exercício 6).
Todas essas funções têm a versão figure-level catplot, com kind="count", "bar", "box", "violin" e outros, que aceita col= para facetas.
Heatmap de correlação com Seaborn
O heatmap é o gráfico mais usado para ver, de uma vez, a correlação entre todas as colunas numéricas de um DataFrame. O fluxo tem duas etapas: calcular a matriz com pandas e desenhar com sns.heatmap.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import matplotlib.pyplot as plt
import seaborn as sns
pinguins = sns.load_dataset("penguins")
medidas = pinguins.select_dtypes("number").rename(columns={
"bill_length_mm": "bico_comp",
"bill_depth_mm": "bico_alt",
"flipper_length_mm": "nadadeira",
"body_mass_g": "massa",
})
correlacao = medidas.corr()
print(correlacao.round(2))
plt.figure(figsize=(7, 5))
ax = sns.heatmap(correlacao, annot=True, fmt=".2f", cmap="coolwarm",
vmin=-1, vmax=1, square=True, linewidths=0.5)
ax.set_title("Correlação entre as medidas dos pinguins")
plt.show()
Saída:
1
2
3
4
5
bico_comp bico_alt nadadeira massa
bico_comp 1.00 -0.24 0.66 0.60
bico_alt -0.24 1.00 -0.58 -0.47
nadadeira 0.66 -0.58 1.00 0.87
massa 0.60 -0.47 0.87 1.00
O que o gráfico mostra: uma grade 4 x 4 com o valor de cada correlação na célula. A diagonal (1,00) e o par nadadeira x massa (0,87) ficam vermelho-escuro: pinguins com nadadeira maior tendem a ser mais pesados. A linha da altura do bico fica azulada, porque ela se correlaciona negativamente com as demais.
annot=True com fmt=".2f" escreve os valores; cmap="coolwarm" é um mapa divergente (azul negativo, vermelho positivo); vmin=-1, vmax=1 fixam a escala, senão a cor mais forte seria o menor valor encontrado; e select_dtypes("number") (ou corr(numeric_only=True)) descarta as colunas de texto, que quebrariam o cálculo.
O heatmap também serve para qualquer tabela numérica, não só correlação. Com pivot, os voos viram uma grade mês x ano:
1
2
3
4
5
6
7
voos = sns.load_dataset("flights")
tabela = voos.pivot(index="month", columns="year", values="passengers")
print(tabela.iloc[:3, :4])
plt.figure(figsize=(9, 5))
sns.heatmap(tabela, cmap="YlGnBu")
plt.show()
Saída:
1
2
3
4
5
year 1949 1950 1951 1952
month
Jan 112 115 145 171
Feb 118 126 150 180
Mar 132 141 178 193
O que o gráfico mostra: 12 linhas (meses) por 12 colunas (anos), do amarelo-claro (poucos passageiros) ao azul-escuro (muitos). As cores escurecem da esquerda para a direita (crescimento ano a ano), e as linhas de julho e agosto são as mais escuras em cada ano (pico das férias). A célula mais escura é julho de 1960, com 622 passageiros.
Como personalizar e salvar gráficos do Seaborn
O visual global se ajusta com sns.set_theme(), que aceita style ("darkgrid", "whitegrid", "dark", "white", "ticks"), palette (paleta de cores) e context ("paper", "notebook", "talk", "poster", que escala fontes e linhas). Tudo que é detalhe de eixo continua sendo Matplotlib. Veja um painel com dois gráficos axes-level lado a lado e um gráfico figure-level com facetas:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(style="ticks", palette="deep", context="talk")
gorjetas = sns.load_dataset("tips")
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 4))
sns.histplot(data=gorjetas, x="tip", ax=ax1)
sns.boxplot(data=gorjetas, x="day", y="tip", hue="day", palette="Set2", legend=False, ax=ax2)
ax1.set_title("Distribuição das gorjetas")
ax2.set_title("Gorjeta por dia")
sns.despine()
fig.tight_layout()
fig.savefig("painel.png", dpi=150)
g = sns.relplot(data=gorjetas, x="total_bill", y="tip", col="time", height=4, aspect=1.2)
g.set_axis_labels("Conta (US$)", "Gorjeta (US$)")
g.set_titles("Refeição: {col_name}")
g.figure.suptitle("Conta x gorjeta", y=1.03)
g.savefig("facetas.png", dpi=150)
print([ax.get_title() for ax in g.axes.flat])
Saída:
1
['Refeição: Lunch', 'Refeição: Dinner']
O que os arquivos mostram: painel.png tem o histograma das gorjetas à esquerda e um boxplot por dia à direita, cada caixa com uma cor da paleta Set2, sem as bordas de cima e da direita (despine) e com fontes grandes (context="talk"). facetas.png tem duas dispersões lado a lado com os títulos personalizados. Regras práticas:
- Em funções axes-level, o tamanho vem do
figsizedo Matplotlib e o posicionamento doax=. Salve complt.savefig()oufig.savefig(). - Em funções figure-level, o tamanho vem de
height(altura de cada painel, em polegadas) easpect(largura = height x aspect). Salve comg.savefig(). - No Seaborn 0.13,
palettesemhueestá obsoleto. Para colorir cada barra ou caixa, repita a coluna do X nohuee passelegend=False, como no boxplot acima.
Chame plt.savefig() antes de plt.show(): depois que a janela é fechada, a figura é descartada e o arquivo sai em branco.
Todo gráfico bom nasce de dados bem manipulados em Python puro: listas, dicionários, funções e arquivos. Firmar essa base é o que fazemos na Jornada Python, do zero ao avançado:
Qual gráfico do Seaborn usar
| Pergunta que você quer responder | Tipo de dado | Função axes-level | Figure-level |
|---|---|---|---|
| Como os valores de uma coluna se distribuem? | 1 numérica |
histplot, kdeplot
|
displot |
| Duas variáveis numéricas andam juntas? | 2 numéricas |
scatterplot, regplot
|
relplot, lmplot
|
| Como algo evolui no tempo? | Tempo + numérica | lineplot |
relplot(kind="line") |
| Quantos registros há por categoria? | 1 categórica | countplot |
catplot(kind="count") |
| Qual a média de um valor por categoria? | Categórica + numérica |
barplot, pointplot
|
catplot(kind="bar") |
| Como a distribuição muda entre grupos? | Categórica + numérica |
boxplot, violinplot
|
catplot(kind="box") |
| Quais colunas estão correlacionadas? | Várias numéricas |
heatmap da corr()
|
pairplot |
Painel com subplots do Matplotlib pede axes-level; painéis por categoria com uma linha de código pedem figure-level.
Erros comuns
Estes são os erros e avisos que mais aparecem com Seaborn, com a última linha real da mensagem.
Nome de coluna errado (ValueError)
1
sns.histplot(data=gorjetas, x="Total_Bill")
1
ValueError: Could not interpret value `Total_Bill` for `x`. An entry with this name does not appear in `data`.
Correção: os nomes diferenciam maiúsculas de minúsculas. Confira com print(gorjetas.columns) e use x="total_bill".
Heatmap de correlação com colunas de texto (ValueError)
1
sns.heatmap(gorjetas.corr())
1
ValueError: could not convert string to float: 'No'
Correção: desde o pandas 2.0, corr() não ignora mais colunas de texto sozinho. Use gorjetas.corr(numeric_only=True) ou gorjetas.select_dtypes("number").corr().
Tratar um FacetGrid como Axes (AttributeError)
1
2
g = sns.displot(data=gorjetas, x="total_bill")
g.set_title("Contas")
1
AttributeError: 'FacetGrid' object has no attribute 'set_title'. Did you mean: 'set_titles'?
Correção: funções figure-level devolvem um FacetGrid. Para um título geral, use g.figure.suptitle("Contas"); para o título de cada painel, g.set_titles(...). Se só precisa de um gráfico, troque por ax = sns.histplot(...) e aí ax.set_title() funciona. Pelo mesmo motivo, sns.displot(..., ax=ax) ignora o ax e emite um UserWarning.
load_dataset sem internet ou com nome errado (URLError, ValueError)
1
2
sns.load_dataset("tips") # sem conexão e sem cache
sns.load_dataset("gorjetas") # nome que não existe
1
2
urllib.error.URLError: <urlopen error [Errno 111] Connection refused>
ValueError: 'gorjetas' is not one of the example datasets.
Correção: o primeiro erro aparece offline (a mensagem exata varia conforme a falha de rede); use o bloco try/except com DataFrame gerado mostrado acima ou leia um CSV local. O segundo pede um nome válido: sns.get_dataset_names() lista todos (tips, flights, penguins, iris, titanic, diamonds e outros).
Parâmetros obsoletos: palette sem hue e ci (FutureWarning)
1
2
sns.barplot(data=gorjetas, x="day", y="total_bill", palette="viridis")
sns.barplot(data=gorjetas, x="day", y="total_bill", ci=None)
1
2
FutureWarning: Passing `palette` without assigning `hue` is deprecated and will be removed in v0.14.0. Assign the `x` variable to `hue` and set `legend=False` for the same effect.
FutureWarning: The `ci` parameter is deprecated. Use `errorbar=None` for the same effect.
Correção: não é erro ainda, mas vai quebrar na 0.14. Muitos tutoriais antigos usam ci=. Escreva sns.barplot(data=gorjetas, x="day", y="total_bill", hue="day", palette="viridis", legend=False) e errorbar=None (ou errorbar="sd", errorbar=("ci", 95)).
Exercícios resolvidos
Tente resolver cada exercício antes de abrir a solução. Todos os códigos foram executados e as saídas conferidas; em todos, considere import matplotlib.pyplot as plt e import seaborn as sns já feitos e gorjetas = sns.load_dataset("tips") carregado quando o exercício usar o dataset de gorjetas.
Exercício 1. Crie um histograma da coluna tip com 10 barras e o título “Distribuição das gorjetas”. Confirme pelo código quantas barras foram desenhadas.
Ver solução
1
2
3
4
ax = sns.histplot(data=gorjetas, x="tip", bins=10)
ax.set(title="Distribuição das gorjetas", xlabel="Gorjeta (US$)")
print(len(ax.patches), ax.get_title())
plt.show()
Saída: 10 Distribuição das gorjetas
Cada barra do histograma é um retângulo guardado em ax.patches. O gráfico mostra a maior parte das gorjetas entre 2 e 4 dólares, com poucas acima de 6.
Exercício 2. Faça um gráfico de barras com a gorjeta média por dia, sem barra de erro, e imprima a altura de cada barra.
Ver solução
1
2
3
4
ax = sns.barplot(data=gorjetas, x="day", y="tip", errorbar=None)
alturas = [round(float(barra.get_height()), 2) for barra in ax.patches]
print(alturas)
plt.show()
Saída: [2.77, 2.73, 2.99, 3.26]
O barplot calcula a média por categoria (quinta, sexta, sábado, domingo). errorbar=None substitui o antigo ci=None.
Exercício 3. Crie a coluna pct_gorjeta (gorjeta como porcentagem da conta) e compare almoço e jantar com um boxplot. A mediana muda muito?
Ver solução
1
2
3
4
5
6
gorjetas["pct_gorjeta"] = gorjetas["tip"] / gorjetas["total_bill"] * 100
ax = sns.boxplot(data=gorjetas, x="time", y="pct_gorjeta")
ax.set(xlabel="Refeição", ylabel="Gorjeta (% da conta)")
print(gorjetas.groupby("time", observed=True)["pct_gorjeta"].median().round(1))
plt.show()
Saída:
1
2
3
4
time
Lunch 15.4
Dinner 15.5
Name: pct_gorjeta, dtype: float64
Não muda: a mediana fica em torno de 15% nos dois turnos. O jantar tem gorjetas maiores em dólares porque as contas são maiores, não porque as pessoas são mais generosas. Essa é a vantagem de olhar a proporção.
Exercício 4. Com o dataset penguins (removendo linhas com dados faltantes), faça um gráfico de dispersão do comprimento da nadadeira contra a massa, colorido por espécie. Qual espécie é a mais pesada?
Ver solução
1
2
3
4
5
6
pinguins = sns.load_dataset("penguins").dropna()
ax = sns.scatterplot(data=pinguins, x="flipper_length_mm", y="body_mass_g", hue="species")
ax.set(xlabel="Nadadeira (mm)", ylabel="Massa (g)")
print(len(pinguins), ax.get_legend().get_title().get_text())
print(pinguins.groupby("species")["body_mass_g"].mean().round())
plt.show()
Saída:
1
2
3
4
5
6
333 species
species
Adelie 3706.0
Chinstrap 3733.0
Gentoo 5092.0
Name: body_mass_g, dtype: float64
Gentoo, com média de 5092 g. No gráfico, os pontos Gentoo formam um grupo separado no canto superior direito (nadadeiras maiores e mais massa), enquanto Adelie e Chinstrap se misturam na parte de baixo.
Exercício 5. Monte o heatmap de correlação das colunas numéricas do penguins e descubra, pelo código, qual par de colunas diferentes tem a correlação mais forte (em valor absoluto).
Ver solução
1
2
3
4
5
6
7
8
pinguins = sns.load_dataset("penguins")
correlacao = pinguins.corr(numeric_only=True)
pares = correlacao.where(correlacao < 1).stack()
print(pares.abs().idxmax(), round(pares.abs().max(), 2))
sns.heatmap(correlacao, annot=True, fmt=".2f", cmap="coolwarm", vmin=-1, vmax=1)
plt.show()
Saída: ('flipper_length_mm', 'body_mass_g') 0.87
O where(correlacao < 1) esconde a diagonal (sempre 1), o stack() transforma a matriz numa série de pares e o idxmax() devolve o par com maior valor absoluto.
Exercício 6. Sem usar load_dataset, gere um DataFrame com 30 vendas para cada uma de três lojas (Centro com média 120, Shopping com média 150 e Bairro com média 90) e compare as lojas com um violinplot.
Ver solução
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import numpy as np
import pandas as pd
rng = np.random.default_rng(7)
vendas = pd.DataFrame({
"loja": np.repeat(["Centro", "Shopping", "Bairro"], 30),
"valor": np.concatenate([
rng.normal(120, 15, 30),
rng.normal(150, 25, 30),
rng.normal(90, 10, 30),
]).round(2),
})
ax = sns.violinplot(data=vendas, x="loja", y="valor", inner="quart")
print(vendas.groupby("loja")["valor"].median().round(1).sort_values())
plt.show()
Saída:
1
2
3
4
5
loja
Bairro 88.0
Centro 116.2
Shopping 150.4
Name: valor, dtype: float64
A semente fixa (default_rng(7)) garante os mesmos números em toda execução. No gráfico, o violino do Shopping é o mais alto e mais esticado (desvio padrão 25), e o do Bairro é o mais baixo e compacto (desvio 10).
Exercício 7 (questão de prova). Qual das funções abaixo é figure-level no Seaborn?
a) histplot
b) scatterplot
c) displot
d) boxplot
Ver solução
Resposta: c. displot cria a figura inteira, aceita col=/row= e devolve um FacetGrid. As outras três são axes-level: desenham num único Axes e aceitam ax=. As figure-level principais são relplot, displot e catplot.
Exercício 8 (questão de prova). Em sns.scatterplot(data=df, x="altura", y="peso", ???="sexo"), qual parâmetro faz os pontos terem cores diferentes para cada valor da coluna sexo, com legenda automática?
a) color
b) hue
c) palette
d) style
Ver solução
Resposta: b. hue mapeia uma coluna para cores. color define uma cor única para todos os pontos, palette escolhe quais cores o hue vai usar (não diz qual coluna colorir) e style muda o formato do marcador, não a cor.
Quer firmar a base de Python por trás da análise de dados, de estruturas de dados a automação de planilhas, com projetos guiados? Conheça o nosso curso de Python completo, a Jornada Python. E, para reforçar a base, veja a nossa lista de exercícios de Python.
Conclusão
Neste guia de Seaborn com Python, você aprendeu:
✅ Distribuição - histplot, kdeplot e displot
✅ Relação - scatterplot, lineplot e lmplot
✅ Categóricos - countplot, barplot, boxplot e violinplot
✅ Heatmap - Correlação com corr(numeric_only=True) e escala de -1 a 1
✅ Axes-level vs figure-level - ax= e figsize de um lado, col=, height e FacetGrid do outro
✅ Personalização - set_theme, paletas e como salvar
O próximo passo é a galeria oficial do Seaborn e a referência da API.
Se ficou com alguma dúvida, fique à vontade para deixar um comentário no box aqui embaixo! Será um prazer te responder! ![]()
Perguntas frequentes
O que é o Seaborn no Python?
Seaborn é uma biblioteca de visualização estatística construída sobre o Matplotlib e integrada ao pandas. Você passa um DataFrame e o nome das colunas, e ela cria histogramas, gráficos de dispersão, boxplots, heatmaps e outros, já com estilo, legenda e agregações estatísticas (médias, intervalos de confiança, densidade). É instalada com pip install seaborn e importada como import seaborn as sns.
Qual a diferença entre Seaborn e Matplotlib?
O Matplotlib é a base: controla cada detalhe do gráfico, mas exige mais código. O Seaborn usa o Matplotlib por baixo e oferece funções de alto nível que entendem DataFrames, agrupam por categoria com hue e calculam estatísticas sozinhas. Na prática, você cria o gráfico com Seaborn e faz ajustes finos (títulos, eixos, tamanho) com Matplotlib.
Como fazer um heatmap de correlação com Seaborn?
Calcule a matriz de correlação com pandas e passe para sns.heatmap: sns.heatmap(df.corr(numeric_only=True), annot=True, fmt='.2f', cmap='coolwarm', vmin=-1, vmax=1). O numeric_only=True ignora colunas de texto (sem ele o pandas 2 gera ValueError), annot=True escreve os valores nas células e vmin/vmax fixam a escala de -1 a 1.
O que faz o parâmetro hue no Seaborn?
O hue recebe o nome de uma coluna e colore os elementos do gráfico de acordo com ela, criando a legenda automaticamente. Por exemplo, sns.scatterplot(data=df, x='total_bill', y='tip', hue='smoker') pinta os pontos de fumantes e não fumantes com cores diferentes. Parâmetros parecidos são style (formato do marcador) e size (tamanho).
Qual a diferença entre histplot e displot?
histplot é uma função axes-level: desenha em um único eixo do Matplotlib e aceita ax= para ser colocada num subplot. displot é figure-level: cria a figura inteira e permite dividir o gráfico em painéis com col= e row=, devolvendo um FacetGrid. O mesmo vale para scatterplot/relplot e boxplot/catplot.
load_dataset do Seaborn precisa de internet?
Sim, na primeira vez. sns.load_dataset('tips') baixa o arquivo CSV do repositório seaborn-data no GitHub e guarda uma cópia em cache (por padrão em ~/seaborn-data). Sem conexão e sem cache, ele gera URLError. Em ambientes offline, carregue seus próprios dados com pd.read_csv ou gere um DataFrame no código.
Como salvar um gráfico do Seaborn em arquivo?
Para funções axes-level (histplot, scatterplot, boxplot), use plt.savefig('grafico.png', dpi=150, bbox_inches='tight') antes de plt.show(). Para funções figure-level (displot, relplot, catplot), use o objeto devolvido: g = sns.relplot(...) e depois g.savefig('grafico.png', dpi=150). O formato é definido pela extensão: png, svg, pdf.
Em uma questão de prova, qual função do Seaborn é figure-level: histplot, scatterplot, displot ou boxplot?
A resposta é displot. As funções figure-level do Seaborn são relplot, displot e catplot (além de lmplot, jointplot e pairplot): elas criam a figura inteira e aceitam col= e row= para facetas. histplot, scatterplot e boxplot são axes-level e desenham em um único eixo.
"Porque o Senhor dá a sabedoria, e da sua boca vem a inteligência e o entendimento" Pv 2:6