Gráficos de Dispersão

Autor

Douglas Braga

Nota

Esta seção corresponde a Scatterplots, do capítulo 3 de Grus (2019).

Um gráfico de dispersão é a escolha certa para visualizar a relação entre dois conjuntos de dados pareados.

Por exemplo, a relação entre o número de amigos que os usuários têm e quantos minutos por dia eles passam no site:

from matplotlib import pyplot as plt

friends = [70, 65, 72, 63, 71, 64, 60, 64, 67]
minutes = [175, 170, 205, 120, 220, 130, 105, 145, 190]
labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']

plt.scatter(friends, minutes)

# rotula cada ponto
for label, friend_count, minute_count in zip(labels, friends, minutes):
    plt.annotate(label,
                 xy=(friend_count, minute_count),  # põe o rótulo no ponto
                 xytext=(5, -5),                   # mas ligeiramente deslocado
                 textcoords='offset points')

plt.title("Minutos diários vs. número de amigos")
plt.xlabel("# de amigos")
plt.ylabel("minutos diários no site")
plt.show()
Figura 16.1: Minutos diários versus número de amigos

O zip aparece de novo, agora percorrendo três listas paralelas de uma vez — rótulos, x e y — para anotar cada ponto.

plt.annotate com textcoords='offset points' desloca o rótulo alguns pixels em relação ao ponto, em vez de posicioná-lo em coordenadas de dados.

A diferença importa: um deslocamento em coordenadas de dados mudaria de tamanho conforme a escala do gráfico, e os rótulos se sobreporiam aos pontos em alguns casos e ficariam longe demais em outros.

Eixos incomparáveis

Aqui está a segunda distorção do capítulo, e ela é mais sutil que a do eixo truncado.

Se você está desenhando um gráfico de dispersão de variáveis comparáveis, pode obter uma imagem enganosa se deixar o matplotlib escolher a escala sozinho:

test_1_grades = [99, 90, 85, 97, 80]
test_2_grades = [100, 85, 60, 90, 70]

plt.scatter(test_1_grades, test_2_grades)
plt.title("Os eixos não são comparáveis")
plt.xlabel("nota da prova 1")
plt.ylabel("nota da prova 2")
plt.show()
Figura 16.2: Os eixos não são comparáveis

Olhando esse gráfico, parece que a variação na prova 2 é bem maior que na prova 1 — os pontos se espalham muito mais na vertical.

Se acrescentarmos uma chamada a plt.axis("equal"), o quadro muda:

plt.scatter(test_1_grades, test_2_grades)
plt.axis("equal")
plt.title("Os eixos são comparáveis")
plt.xlabel("nota da prova 1")
plt.ylabel("nota da prova 2")
plt.show()
Figura 16.3: Os eixos são comparáveis
AvisoDe novo: nenhum número mudou

Os dois gráficos mostram os mesmos cinco pontos, com os mesmos rótulos e sem nenhum valor incorreto.

O primeiro sugere que as duas provas se comportaram de forma muito diferente. O segundo mostra o que é verdade: a variação na prova 2 é de fato maior, mas nem de longe na proporção que o primeiro gráfico sugere.

A causa é que o matplotlib escolheu escalas diferentes para cada eixo, para preencher a área disponível. É um padrão razoável na maioria dos casos — e enganoso justamente quando as duas variáveis estão na mesma unidade e a comparação entre elas é o ponto.

Junte com a lição da seção 3.2 e o padrão fica claro.

Nos dois casos, a distorção veio de uma decisão sobre escala, não sobre dado. Nos dois casos, o gráfico enganoso era o padrão da ferramenta — ninguém precisou tentar enganar.

É por isso que a defesa não pode ser desconfiar de má-fé. A defesa é olhar os eixos antes de olhar o desenho: onde começam, em que unidade estão, e se são comparáveis entre si.

Quando as duas variáveis são comparáveis — notas de duas provas, medições antes e depois, valores previstos contra observados —, plt.axis("equal") deveria ser reflexo. Você vai ver essa chamada nos capítulos de regressão, quando compararmos o que o modelo previu com o que de fato aconteceu.

Grus, Joel. 2019. Data Science from Scratch: First Principles with Python. 2nd ed. O’Reilly Media.