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 pltfriends = [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 pontofor label, friend_count, minute_count inzip(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.