Curso matplotlib - Elementos auxiliares (Anotações)

4 minute read


O plt.annotate() já foi utilizado anteriormente, mas não foi estudado a fundo. Em geral, esta é a melhor forma de adicionar texto nos gráficos, especialmente se o este texto estiver relacionado a algum ponto do gráfico.

O elemento plt.annotate() recebe pelo menos dois parâmetros, sendo o primeiro parâmetro o text, que é o texto que será anotado (que deve ser uma str), e o segundo é o parâmetro xy, que é deve ser uma tuple de dois elementos (int ou float) com os valores de x e y referentes a posição onde o texto será anotado.

Por exemplo:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]))
plt.show()

Figura 1 - Gráfico de dispersão com texto inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto inserido com o plt.annotate()


Entretanto, o parâmetro xy define onde a anotação inicia. O parâmetro utilizado para definir onde o texto é realmente inserido é o parâmetro xytext, que também recebe uma tuple com as coordenadas xy.

Por exemplo, passando o mesmo valor para xy e xytext, obtemos o mesmo resultado obtido anteriormente (Figura 1):

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0],y[0]))
plt.show()

Figura 2 - Gráfico de dispersão com texto inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto inserido com o plt.annotate()


Mas ao passar valores diferentes para xy e xytext, obtemos um comportamento diferente:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 0.3,y[0] + 0.5))
plt.show()

Figura 3 - Gráfico de dispersão com texto inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto inserido com o plt.annotate()


Annotações com setas

Este espaço “vazio” é importante para a adição de elementos entre os pontos definidos como xy e xytext. Por exemplo, podemos adicionar uma seta dentro de plt.annotate(), passando o parâmetro arrowprops.

Este parâmetro recebe um dict com uma série de keys para inserir a seta. Para alterar a espessura dessa seta, passamos um número (int ou float) através da key width:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 0.3,y[0] + 0.5),  
             arrowprops={'width': 2})
plt.show()

Figura 4 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto com flecha inserido com o plt.annotate()


Espessura da ponta da seta

Para alterar a espessura da cabeça da seta, passamos um número (int ou float) para a key headwidth:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 0.3,y[0] + 0.5),  
             arrowprops={'width': 2, 'headwidth': 20})
plt.show()

Figura 5 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o **matplotlib**, com texto com flecha inserido com o plt.annotate()


Comprimento da ponta seta

Para alterar o comprimento da cabeça da seta, passamos um número (int ou float) para a key headlength:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 0.3,y[0] + 0.5),  
             arrowprops={'width': 2, 'headwidth': 20, 'headlength': 20})
plt.show()

Figura 6 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto com flecha inserido com o plt.annotate()


Espaçamento entre o início e fim da seta

Podemos ainda adicionar um espaçamento nos limites do elemento, de forma a evitar que a seta fique exatamente em cima do ponto. Fazemos isso passando um número (int ou float) para a key shrink:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 0.3,y[0] + 0.5),  
             arrowprops={'width': 2, 'headwidth': 20, 'headlength': 20, 'shrink': 0.1,})
plt.show()

Figura 7 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o **matplotlib**, com texto com flecha inserido com o plt.annotate()


Outras edições

Para alterar a cor, espessura da linha, estilo de linha, etc, utilizamos os parâmetros normalmente que vimos anteriormente, como o facecolor, linestyle,linewidth, etc. Por exemplo:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + 2,y[0] + 1.5),  
             arrowprops={'width': 1, 'headwidth': 20, 'headlength': 20, 'shrink': 0.01,
                         'facecolor': 'k', 'linewidth': 2, 'linestyle': ':'})
plt.show()

Figura 8 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o **matplotlib**, com texto com flecha inserido com o plt.annotate()


Estilos pré definidos

Temos a opção de passar a key arrowstyle que tem uma série de values pré-definidos com estilos. Entretanto, ao utilizar esta key, não podemos passar as key widht, headwidht, headlength e shrink.

Por exemplo:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", (x[0], y[0]), xytext=(x[0] + .3, y[0] + 0.5),  
             arrowprops={'arrowstyle': '-['})
plt.show()

Figura 9 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o **matplotlib**, com texto com flecha inserido com o plt.annotate()


Todos os estilos disponíveis estão exemplificados na figura abaixo, sendo que o valor anotado é o nome do estilo que deve ser passado como value para a key arrowstyle.

estilos de flechas disponíveis em plt.annotate()


Click aqui para acessar o notebook utilizado para desenhar a imagem acima.

Um detalhe importante ao utilizar a anotação com setas, é a direção das setas, especialmente quando queremos que a seta seja paralela aos eixos. Por exemplo:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", xy=(x[1], y[1]), xytext=(x[2] + .3, y[1]),  
             arrowprops={'arrowstyle': '->'})
plt.show()

Figura 10 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto com flecha inserido com o plt.annotate()


Observe que, apesar dos valores de y em xy e em xytext serem os mesmos (y[1]) a linha da seta não é paralela ao eixo x. Para confirmar isto, vou adicionar uma reta paralela ao eixo x em y[1]:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", xy=(x[1], y[1]), xytext=(x[2] + .3, y[1]),  
             arrowprops={'arrowstyle': '->'})
plt.axhline(y=y[1], xmin=0, xmax=1)
plt.show()

Figura 11 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o matplotlib, com texto com flecha inserido com o plt.annotate()


Isto acontece pois a seta é direcionada ao ponto xy vinda do centro do texto. Como a base do texto é o ponto setado em xytext, temos esta pequena inclinação.

Para contornar isto, basta passar o parâmetro va (de vertical alignment) em plt.annotate() como center:

plt.figure(figsize=(8,6))
plt.scatter(x,y)
plt.annotate("minha anotação", xy=(x[1], y[1]), xytext=(x[2] + .3, y[1]), va='center',
             arrowprops={'arrowstyle': '->'})
plt.axhline(y=y[1], xmin=0, xmax=1)
plt.show()

Figura 12 - Gráfico de dispersão com texto com flecha inserido com o plt.annotate().

gráfico de dispersão genérico desenhado com o **matplotlib**, com texto com flecha inserido com o plt.annotate()


Maiores detalhes sobre este “problema” nesta thread no github.

Mais detalhes na sobre o plt.annotate()na documentação.

Qual é a principal diferença os elementos plt.text() e o plt.annotate()?

O plt.text() é utilizado para inserir um texto genérico em uma posição arbitrária do gráfico, enquanto que o plt.annotate() é utilizado para inserir um texto em uma posição em relação a um ponto do gráfico.

O plt.annotate() é utilizado para inserir apenas números, enquanto que o plt.text() é utilizado para inserir apenas texto.

O plt.annotate() é utilizado para inserir um texto genérico em uma posição arbitrária do gráfico, enquanto que o plt.text() é utilizado para inserir um texto em uma posição em relação a um ponto do gráfico.


Anterior Próximo

Updated: