Gráficos de Dispersão com Matplotlib em Python — Guia Completo
Aprenda a criar e personalizar gráficos de dispersão em Python com Matplotlib. Aborda cor, tamanho, alpha, colorbars, grupos múltiplos e anotações.
A função scatter() do Matplotlib permite visualizar a relação entre duas variáveis numéricas, posicionando um marcador em cada ponto de dados (x, y). Ao contrário de um gráfico de linhas, os gráficos de dispersão não pressupõem ordem nem continuidade — cada ponto existe por si mesmo. Isso os torna a escolha ideal para explorar correlações, identificar clusters e detectar outliers.
Este capítulo cobre tudo, desde o seu primeiro gráfico de dispersão até técnicas profissionais: codificação de cor e tamanho por ponto, transparência, colorbars, gráficos com múltiplos grupos, anotações de pontos e salvamento de arquivos prontos para publicação.
Antes de começar, certifique-se de que o Matplotlib está instalado:
pip install matplotlibSe você é novo no Matplotlib, leia os capítulos Introdução ao Matplotlib e Primeiros Passos primeiro.
Quando Usar um Gráfico de Dispersão
Use um gráfico de dispersão quando:
- Você quer explorar a correlação entre duas variáveis numéricas (altura vs. peso, horas estudadas vs. nota no exame).
- Você precisa detectar clusters — grupos de pontos que se agrupam naturalmente.
- Você quer identificar outliers — pontos distantes da distribuição principal.
- Você está codificando uma terceira variável por meio do tamanho ou cor do marcador (um "gráfico de bolhas" é um gráfico de dispersão em que o tamanho representa uma terceira variável).
Evite gráficos de dispersão quando um eixo representa categorias não ordenadas — um gráfico de barras é mais claro nesse caso. Para tendências ao longo de uma variável contínua ordenada, um gráfico de linhas é mais adequado.
Criando um Gráfico de Dispersão Básico
Passe duas sequências de mesmo comprimento — valores x e valores y — para plt.scatter():
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 4, 5, 4, 7, 8, 6, 9, 10, 12]
plt.scatter(x, y)
plt.title('Basic Scatter Plot')
plt.xlabel('X Values')
plt.ylabel('Y Values')
plt.tight_layout()
plt.show()plt.tight_layout() evita que os rótulos sejam cortados — torne isso um hábito antes de cada chamada a show() ou savefig().
Personalizando o Tamanho dos Marcadores
O parâmetro s controla o tamanho do marcador em pontos ao quadrado (o padrão é 20). Aumente-o para facilitar a visualização dos pontos, especialmente em apresentações:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3, 1, 4, 1, 5, 9, 2, 6]
plt.scatter(x, y, s=120)
plt.title('Larger Markers')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Você também pode passar uma lista ou array para s, de modo que cada ponto tenha seu próprio tamanho — é assim que se codifica uma terceira variável numérica como tamanho de bolha:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [5, 3, 6, 2, 7]
sizes = [100, 300, 50, 400, 200] # third variable encoded as bubble area
plt.scatter(x, y, s=sizes)
plt.title('Bubble Chart — size encodes a third variable')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Personalizando a Cor dos Marcadores
Uma Única Cor para Todos os Pontos
Passe qualquer nome de cor, string hexadecimal ou tupla RGB para c (ou color):
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2, 4, 1, 5, 3]
plt.scatter(x, y, s=100, c='steelblue')
plt.title('Single Color')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Cor por Ponto a partir de uma Variável Numérica
Ao passar um array para c, cada valor é mapeado para uma cor via o colormap especificado em cmap. Adicione plt.colorbar() para mostrar o que as cores representam:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=42)
x = rng.random(50)
y = rng.random(50)
values = rng.random(50) # third variable, e.g. intensity or temperature
scatter = plt.scatter(x, y, s=80, c=values, cmap='viridis')
plt.colorbar(scatter, label='Intensity')
plt.title('Color-Mapped Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()'viridis' é um colormap perceptualmente uniforme, legível em escala de cinza e acessível a leitores com daltonismo. Outras boas opções são 'plasma', 'cividis' e 'coolwarm'.
Controlando a Transparência com alpha
Quando muitos pontos se sobrepõem, formam uma massa opaca que oculta a verdadeira densidade. Defina alpha (0 = totalmente transparente, 1 = totalmente opaco) para revelar a estrutura sobreposta:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=0)
x = rng.normal(loc=0, scale=1, size=300)
y = rng.normal(loc=0, scale=1, size=300)
plt.scatter(x, y, s=40, alpha=0.4)
plt.title('Transparent Markers Reveal Density (alpha=0.4)')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Um bom ponto de partida é alpha=0.4 a 0.6. Ajuste com base na quantidade de pontos que você tem.
Estilizando as Bordas dos Marcadores
Use edgecolors para adicionar uma borda ao redor de cada marcador e linewidths para controlar a espessura da borda. Isso ajuda os pontos a se destacarem em fundos coloridos:
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5, 6]
y = [3, 1, 4, 1, 5, 9]
plt.scatter(x, y, s=150, c='gold', edgecolors='black', linewidths=1.5)
plt.title('Markers with Edges')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Passe edgecolors='none' para remover bordas completamente (este é o padrão para a maioria dos colormaps).
Plotando Múltiplos Grupos
Para comparar grupos, chame plt.scatter() uma vez por grupo e atribua um rótulo. O Matplotlib atribui automaticamente uma cor padrão diferente a cada chamada:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=7)
# Group A — centered around (2, 3)
ax_x = rng.normal(loc=2, scale=0.5, size=30)
ax_y = rng.normal(loc=3, scale=0.5, size=30)
# Group B — centered around (5, 6)
bx_x = rng.normal(loc=5, scale=0.5, size=30)
bx_y = rng.normal(loc=6, scale=0.5, size=30)
# Group C — centered around (8, 2)
cx_x = rng.normal(loc=8, scale=0.5, size=30)
cx_y = rng.normal(loc=2, scale=0.5, size=30)
plt.scatter(ax_x, ax_y, s=60, label='Group A')
plt.scatter(bx_x, bx_y, s=60, label='Group B')
plt.scatter(cx_x, cx_y, s=60, label='Group C')
plt.legend()
plt.title('Multi-Group Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()Cada chamada a scatter() escolhe automaticamente a próxima cor no ciclo de cores padrão. Passe c='red' (ou qualquer cor) para substituir.
Anotando Pontos Individuais
Use plt.annotate() para rotular pontos específicos — útil para destacar outliers ou observações importantes:
import matplotlib.pyplot as plt
cities = ['London', 'Berlin', 'Madrid', 'Rome', 'Paris']
population = [9.0, 3.7, 3.3, 2.8, 2.1] # millions
area = [1572, 892, 604, 1285, 105] # km²
plt.scatter(area, population, s=100, c='steelblue', edgecolors='black', linewidths=0.8)
for i, city in enumerate(cities):
plt.annotate(
city,
xy=(area[i], population[i]),
xytext=(8, 4), # offset in points
textcoords='offset points',
fontsize=9,
)
plt.title('European City Population vs. Area')
plt.xlabel('Area (km²)')
plt.ylabel('Population (millions)')
plt.tight_layout()
plt.show()O padrão xytext + textcoords='offset points' desloca o rótulo levemente para que não fique diretamente sobre o marcador.
Usando Eixos Logarítmicos
Quando os dados abrangem várias ordens de magnitude, os eixos lineares comprimem a maioria dos pontos em um canto. Mude para escala logarítmica com plt.xscale('log') ou plt.yscale('log'):
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=1)
x = np.logspace(1, 5, 60) # 10¹ to 10⁵
y = x * rng.uniform(0.5, 2.0, 60) # roughly proportional, with noise
plt.scatter(x, y, s=40, alpha=0.7)
plt.xscale('log')
plt.yscale('log')
plt.title('Log-Scale Scatter Plot')
plt.xlabel('X (log scale)')
plt.ylabel('Y (log scale)')
plt.tight_layout()
plt.show()Ambos os eixos agora abrangem intervalos uniformes de potências de dez, distribuindo os dados de forma uniforme pela área do gráfico.
Adicionando uma Linha de Regressão
Um gráfico de dispersão exibe pontos individuais; adicionar uma linha de melhor ajuste mostra a tendência geral. Calcule a inclinação e o intercepto com np.polyfit():
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=3)
x = np.linspace(0, 10, 40)
y = 2.5 * x + rng.normal(scale=3, size=40) # linear trend + noise
# Fit a degree-1 polynomial (straight line)
slope, intercept = np.polyfit(x, y, 1)
trend_line = slope * x + intercept
plt.scatter(x, y, s=50, label='Data points', alpha=0.7)
plt.plot(x, trend_line, color='red', linewidth=2, label=f'Trend (slope={slope:.2f})')
plt.legend()
plt.title('Scatter Plot with Regression Line')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.show()np.polyfit(x, y, 1) retorna [slope, intercept] para a linha de melhor ajuste pelos pontos.
Salvando um Gráfico de Dispersão em um Arquivo
Use plt.savefig() em vez de plt.show() para gravar o gráfico no disco. Chame-o antes de plt.show() — após o show(), a figura é limpa:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=9)
x = rng.random(60)
y = rng.random(60)
plt.scatter(x, y, s=60, alpha=0.6, c='teal', edgecolors='white', linewidths=0.5)
plt.title('Saved Scatter Plot')
plt.xlabel('X')
plt.ylabel('Y')
plt.tight_layout()
plt.savefig('scatter.png', dpi=150) # PNG at 150 DPI
plt.savefig('scatter.pdf') # vector PDF — best for publication
plt.show()Opções de formato comuns: 'png' (raster, web), 'pdf' (vetor, publicação), 'svg' (vetor, web). Aumente dpi para 300 para rasters com qualidade de impressão.
scatter() vs plot() — Qual Usar?
Ambas as funções podem desenhar gráficos somente com marcadores, mas servem a propósitos diferentes:
| Recurso | plt.scatter() | plt.plot() |
|---|---|---|
Tamanho por ponto (s) | Sim — passe um array | Não |
Cor por ponto (c) | Sim — passe um array | Não (uma cor por chamada) |
| Suporte a colormap | Sim (cmap) | Limitado |
| Desempenho em grandes conjuntos de dados | Mais lento | Mais rápido |
| Linha de conexão | Não | Sim |
Use scatter() quando precisar de estilização por ponto (cor ou tamanho varia com os dados). Use plot(marker='o', linestyle='None') para gráficos simples de marcadores em grandes conjuntos de dados onde a velocidade importa. Consulte o capítulo Marcadores do Matplotlib para mais informações sobre estilos de marcadores.
Exemplo Completo
O seguinte script autocontido combina as técnicas mais úteis — mapeamento de cores, codificação de tamanho, transparência, colorbar e legenda:
import matplotlib.pyplot as plt
import numpy as np
rng = np.random.default_rng(seed=42)
n = 80
x = rng.standard_normal(n)
y = 0.8 * x + rng.standard_normal(n) * 0.6 # correlated
sizes = rng.uniform(30, 200, n) # bubble area
values = rng.random(n) # third variable for color
fig, ax = plt.subplots(figsize=(8, 5))
sc = ax.scatter(
x, y,
s=sizes,
c=values,
cmap='plasma',
alpha=0.75,
edgecolors='white',
linewidths=0.5,
)
plt.colorbar(sc, ax=ax, label='Intensity')
ax.set_title('Comprehensive Scatter Plot Example', fontsize=13)
ax.set_xlabel('X Variable')
ax.set_ylabel('Y Variable (correlated)')
fig.tight_layout()
plt.savefig('scatter_complete.png', dpi=150)
plt.show()Pontos principais:
fig, ax = plt.subplots()fornece objetos explícitos de figura e eixos — a abordagem recomendada para qualquer coisa além de um protótipo rápido.ax.scatter()em um objetoAxesse comporta de forma idêntica aplt.scatter().plt.colorbar(sc, ax=ax, label='...')anexa a colorbar aos eixos específicos.
Boas Práticas
- Mostre a escala. Se você usar
ccom um colormap, sempre adicione uma colorbar para que os leitores saibam o que as cores representam. - Evite sobreplotagem. Para mais de ~500 pontos, defina
alpha < 1ou mude para um histograma 2D (plt.hist2d()) ou um gráfico hexbin (plt.hexbin()). - Escolha colormaps acessíveis.
'viridis','plasma'e'cividis'são perceptualmente uniformes e amigáveis para daltônicos. Evite'jet'e'rainbow'. - Rotule os eixos com unidades.
plt.xlabel('Altura (cm)')é mais informativo do queplt.xlabel('Altura'). - Adicione um título que declare a conclusão. "Altura vs. Peso — correlação positiva" é mais útil do que "Gráfico de Dispersão".
Capítulos Relacionados
- Introdução ao Matplotlib — visão geral da biblioteca e instalação
- Primeiros Passos com Matplotlib — seus primeiros gráficos
- Gráficos de Linhas com Matplotlib — tendências ao longo de variáveis contínuas
- Gráficos de Barras com Matplotlib — comparando categorias discretas
- Histogramas com Matplotlib — distribuição de uma única variável
- Marcadores do Matplotlib — todos os estilos e opções de personalização de marcadores
- Subplots do Matplotlib — combinando múltiplos gráficos em uma figura