HOWTO · Matplotlib
Definir o tamanho dos marcadores em um gráfico de dispersão Matplotlib
Defina um tamanho único ou um tamanho por ponto com scatter, dimensione as áreas corretamente e corrija um array de tamanhos incompatível.
Nesta página
Use o argumento s de Axes.scatter para definir o tamanho dos marcadores em um gráfico de dispersão do Matplotlib. Um escalar aplica a mesma área nominal a todos os pontos; uma lista ou matriz unidimensional atribui uma área a cada ponto e deve ter o mesmo comprimento de x e y.
Definir o tamanho dos marcadores com s
Passe o argumento s para Axes.scatter a fim de definir o tamanho do marcador em um gráfico de dispersão Matplotlib. Um escalar como s=80 atribui a mesma área nominal a todos os pontos. Uma lista ou um array unidimensional atribui uma área a cada ponto, mas precisa ter a mesma quantidade de valores que x e y. Por exemplo, use ax.scatter(x, y, s=80) para um tamanho único ou ax.scatter(x, y, s=[20, 40, 80, 160]) para quatro pontos com tamanhos diferentes.
Use scatter quando o tamanho variar por observação. O método relacionado plot usa markersize para uma única dimensão linear do marcador.
Usar um tamanho único ou um tamanho por ponto
O exemplo determinístico a seguir coloca uma coleção de tamanho escalar ao lado de outra cujos tamanhos derivam dos dados. Ele também mapeia os mesmos valores para cores e usa alpha para facilitar a leitura de marcadores sobrepostos. A imagem salva permite inspecionar o resultado sem um backend interativo.
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
values = [1, 2, 4, 7, 11]
sizes = [40 + value * 20 for value in values]
fig, (top, bottom) = plt.subplots(2, 1, figsize=(6, 7), layout="constrained")
uniform = top.scatter(x, y, s=80, color="tab:blue")
varying = bottom.scatter(x, y, s=sizes, c=values, cmap="viridis", alpha=0.75)
top.set(title="s = 80", xlabel="x", ylabel="y")
bottom.set(title="s = [60, 80, 120, 180, 260]", xlabel="x", ylabel="y")
fig.colorbar(varying, ax=bottom)
print("scalar sizes:", uniform.get_sizes().tolist())
print("per-point sizes:", varying.get_sizes().tolist())
fig.savefig("scatter-marker-sizes.webp", dpi=120)
Os dois objetos PathCollection mostram exatamente os valores de s que o Matplotlib armazenou:
scalar sizes: [80]
per-point sizes: [60, 80, 120, 180, 260]
A transformação começa em 40 e soma 20 para cada unidade do dado; assim, o menor valor permanece visível e o maior não domina os eixos. Com dados reais, escolha e documente um limite inferior e superior em vez de passar valores brutos extremos diretamente. A cor pode representar a mesma variável, como acima, ou outra variável; inclua uma barra de cores quando elas tiverem significado quantitativo.
Entender os pontos quadrados (pt²) e o valor padrão
A documentação de Matplotlib para scatter define s em pontos quadrados (pt²), sendo um ponto tipográfico igual a 1/72 de polegada. O padrão é rcParams['lines.markersize'] ** 2. Portanto, s é proporcional à área nominal do marcador, mas s=100 não garante uma forma visível de exatamente 10 × 10 pontos. O caminho do marcador, o DPI da figura e o estilo da borda influenciam seu contorno final.
As bordas têm maior efeito em marcadores pequenos. Quando linewidths é maior que zero e edgecolors está visível, o traço fica centralizado no limite do marcador e aumenta sua extensão efetiva em metade da largura da linha. Use linewidths=0 ou edgecolors="none" ao comparar pequenos marcadores preenchidos quando a borda não deve alterar o tamanho aparente.
O tamanho do marcador é uma medida no espaço de exibição, não uma unidade de dados dos eixos x ou y. Ampliar o gráfico ou mudar os limites dos eixos, portanto, não faz com que o marcador represente um raio nas coordenadas dos dados.
Dimensionar corretamente a área e a largura linear
Multiplicar s por dois dobra a área nominal. Como a extensão linear cresce aproximadamente com a raiz quadrada da área, multiplicar s por quatro torna um marcador de formato semelhante cerca de duas vezes mais largo. Essa é uma regra visual proporcional, não uma garantia geométrica exata para todos os caminhos de marcador.
import matplotlib.pyplot as plt
base = 36
area_sizes = [base, 2 * base, 4 * base]
fig, (top, bottom) = plt.subplots(2, 1, figsize=(6, 7), layout="constrained")
top.scatter([1, 2, 3], [1, 1, 1], s=area_sizes, linewidths=0)
top.set(title="s = [36, 72, 144]", yticks=[])
top.set_xticks([1, 2, 3], ["1", "2", "4"])
bottom.scatter([1], [1], s=10**2, linewidths=0)
(line,) = bottom.plot([2], [1], marker="o", linestyle="none", markersize=10,
color="tab:orange")
bottom.set(title="scatter: s = 10**2 plot: markersize = 10", xlim=(0.5, 2.5), yticks=[])
print("scatter areas:", area_sizes)
print("plot markersize:", line.get_markersize())
fig.savefig("scatter-size-scaling.webp", dpi=120)
Os valores escolhidos e a dimensão do marcador Line2D são:
scatter areas: [36, 72, 144]
plot markersize: 10.0
Escolher scatter(s=...) ou plot(markersize=...)
Use scatter(s=...) em um gráfico de dispersão, especialmente quando cada observação precisar de uma área ou cor própria. Use plot(marker="o", markersize=10) ao desenhar um objeto Line2D cujos nós compartilham o mesmo tamanho do marcador. Conforme documenta a referência de Matplotlib para plot, markersize (ou ms) é um tamanho linear em pontos, não a área em pontos quadrados aceita por scatter.
Embora scatter(s=10**2) e plot(markersize=10) expressem dimensões nominais relacionadas para marcadores circulares, não dependa de uma igualdade exata de pixels. Marcadores de coleções e linhas podem diferir por causa dos caminhos normalizados, das bordas, do backend de renderização e da rasterização.
Corrigir um array de tamanhos incompatível com os pontos
Um valor s não escalar precisa ter o mesmo comprimento que os pontos plotados. Este exemplo captura o diagnóstico da versão atual de Matplotlib para exibi-lo sem um traceback completo:
import matplotlib.pyplot as plt
x = [1, 2, 3]
y = [1, 4, 9]
try:
plt.scatter(x, y, s=[40, 80])
except ValueError as error:
print(f"{type(error).__name__}: {error}")
else:
raise AssertionError("a mismatched size array should fail")
Com o Matplotlib 3.11.2, a saída é:
ValueError: s (size 2) cannot be broadcast to match x and y (size 3)
Versões anteriores do Matplotlib podem escrever o ValueError de outra forma, mas a correção é a mesma: forneça três valores de tamanho para três pontos (x, y) ou passe um único tamanho escalar.