Texto em Gráficos Matplotlib #

Introdução à plotagem e ao trabalho com texto no Matplotlib.

Matplotlib tem amplo suporte a texto, incluindo suporte para expressões matemáticas, suporte truetype para raster e saídas vetoriais, texto separado por nova linha com rotações arbitrárias e suporte Unicode.

Como ele incorpora fontes diretamente em documentos de saída, por exemplo, para postscript ou PDF, o que você vê na tela é o que obtém na cópia impressa. O suporte FreeType produz fontes com suavização muito boas, que ficam bem mesmo em tamanhos raster pequenos. O Matplotlib inclui o seu próprio matplotlib.font_manager(graças a Paul Barrett), que implementa uma plataforma cruzada, algoritmo de localização de fonte compatível com W3C .

O usuário tem um grande controle sobre as propriedades do texto (tamanho da fonte, peso da fonte, localização e cor do texto, etc.) com padrões sensatos definidos no arquivo rc . E significativamente, para aqueles interessados ​​em figuras matemáticas ou científicas, o Matplotlib implementa um grande número de símbolos e comandos matemáticos TeX, suportando expressões matemáticas em qualquer lugar da sua figura.

Comandos básicos de texto #

Os seguintes comandos são usados ​​para criar texto nas interfaces implícitas e explícitas (consulte Matplotlib Application Interfaces (APIs) para obter uma explicação das compensações):

API implícita

API explícita

Descrição

text

text

Adicione texto em um local arbitrário do arquivo Axes.

annotate

annotate

Adicione uma anotação, com uma seta opcional, em um local arbitrário do arquivo Axes.

xlabel

set_xlabel

Adicione um rótulo ao Axeseixo x de.

ylabel

set_ylabel

Adicione um rótulo ao Axeseixo y de.

title

set_title

Adicione um título ao arquivo Axes.

figtext

text

Adicione texto em um local arbitrário do arquivo Figure.

suptitle

suptitle

Adicione um título ao arquivo Figure.

Todas essas funções criam e retornam uma Textinstância, que pode ser configurada com uma variedade de fontes e outras propriedades. O exemplo abaixo mostra todos esses comandos em ação e mais detalhes são fornecidos nas seções a seguir.

import matplotlib
import matplotlib.pyplot as plt

fig = plt.figure()
ax = fig.add_subplot()
fig.subplots_adjust(top=0.85)

# Set titles for the figure and the subplot respectively
fig.suptitle('bold figure suptitle', fontsize=14, fontweight='bold')
ax.set_title('axes title')

ax.set_xlabel('xlabel')
ax.set_ylabel('ylabel')

# Set both x- and y-axis limits to [0, 10] instead of default [0, 1]
ax.axis([0, 10, 0, 10])

ax.text(3, 8, 'boxed italics text in data coords', style='italic',
        bbox={'facecolor': 'red', 'alpha': 0.5, 'pad': 10})

ax.text(2, 6, r'an equation: $E=mc^2$', fontsize=15)

ax.text(3, 2, 'Unicode: Institut für Festkörperphysik')

ax.text(0.95, 0.01, 'colored text in axes coords',
        verticalalignment='bottom', horizontalalignment='right',
        transform=ax.transAxes,
        color='green', fontsize=15)

ax.plot([2], [1], 'o')
ax.annotate('annotate', xy=(2, 1), xytext=(3, 4),
            arrowprops=dict(facecolor='black', shrink=0.05))

plt.show()
subtítulo da figura em negrito, título dos eixos

Rótulos para os eixos x e y #

A especificação dos rótulos para os eixos x e y é direta, por meio dos métodos set_xlabele .set_ylabel

import matplotlib.pyplot as plt
import numpy as np

x1 = np.linspace(0.0, 5.0, 100)
y1 = np.cos(2 * np.pi * x1) * np.exp(-x1)

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('time [s]')
ax.set_ylabel('Damped oscillation [V]')

plt.show()
introdução de texto

Os rótulos x e y são colocados automaticamente para que limpem os rótulos x e y. Compare o gráfico abaixo com o gráfico acima e observe que o rótulo y está à esquerda do gráfico acima.

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('time [s]')
ax.set_ylabel('Damped oscillation [V]')

plt.show()
introdução de texto

Se quiser mover os rótulos, você pode especificar o argumento de palavra-chave labelpad , onde o valor é pontos (1/72", a mesma unidade usada para especificar o tamanho da fonte).

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1*10000)
ax.set_xlabel('time [s]')
ax.set_ylabel('Damped oscillation [V]', labelpad=18)

plt.show()
introdução de texto

Ou os rótulos aceitam todos os Textargumentos de palavra-chave, incluindo position , por meio do qual podemos especificar manualmente as posições dos rótulos. Aqui colocamos o xlabel na extrema esquerda do eixo. Observe que a coordenada y desta posição não tem efeito - para ajustar a posição y, precisamos usar o argumento de palavra-chave labelpad .

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('time [s]', position=(0., 1e6), horizontalalignment='left')
ax.set_ylabel('Damped oscillation [V]')

plt.show()
introdução de texto

Toda a rotulagem neste tutorial pode ser alterada manipulando o matplotlib.font_manager.FontPropertiesmétodo ou por argumentos de palavra-chave nomeados paraset_xlabel

from matplotlib.font_manager import FontProperties

font = FontProperties()
font.set_family('serif')
font.set_name('Times New Roman')
font.set_style('italic')

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.15, left=0.2)
ax.plot(x1, y1)
ax.set_xlabel('time [s]', fontsize='large', fontweight='bold')
ax.set_ylabel('Damped oscillation [V]', fontproperties=font)

plt.show()
introdução de texto

Por fim, podemos usar a renderização nativa do TeX em todos os objetos de texto e ter várias linhas:

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(bottom=0.2, left=0.2)
ax.plot(x1, np.cumsum(y1**2))
ax.set_xlabel('time [s] \n This was a long experiment')
ax.set_ylabel(r'$\int\ Y^2\ dt\ \ [V^2 s]$')
plt.show()
introdução de texto

Títulos #

Os títulos da subtrama são definidos da mesma maneira que os rótulos, mas há os argumentos de palavra-chave loc que podem alterar a posição e a justificação do valor padrão de loc=center.

fig, axs = plt.subplots(3, 1, figsize=(5, 6), tight_layout=True)
locs = ['center', 'left', 'right']
for ax, loc in zip(axs, locs):
    ax.plot(x1, y1)
    ax.set_title('Title with loc at '+loc, loc=loc)
plt.show()
Título com localização ao centro, Título com localização à esquerda, Título com localização à direita

O espaçamento vertical para títulos é controlado via rcParams["axes.titlepad"](padrão: 6.0). Definir um valor diferente move o título.

fig, ax = plt.subplots(figsize=(5, 3))
fig.subplots_adjust(top=0.8)
ax.plot(x1, y1)
ax.set_title('Vertically offset title', pad=30)
plt.show()
Título deslocado verticalmente

Ticks e marcadores #

Colocar marcas e rótulos é um aspecto muito complicado de fazer uma figura. O Matplotlib faz o possível para realizar a tarefa automaticamente, mas também oferece uma estrutura muito flexível para determinar as opções de localização dos ticks e como eles são rotulados.

Terminologia #

Os eixos têm um matplotlib.axis.Axisobjeto para o ax.xaxise ax.yaxisque contém as informações sobre como os rótulos no eixo são dispostos.

A API do eixo é explicada em detalhes na documentação do axis.

Um objeto Axis tem marcações principais e secundárias. O Axis tem métodos Axis.set_major_locatorque Axis.set_minor_locatorusam os dados que estão sendo plotados para determinar a localização dos tiques principais e secundários. Existem também métodos Axis.set_major_formattere Axis.set_minor_formatterque formatam os rótulos dos ticks.

Carrapatos simples #

Freqüentemente, é conveniente simplesmente definir os valores dos ticks e, às vezes, os rótulos dos ticks, substituindo os localizadores e formatadores padrão. Isso é desencorajado porque interrompe a navegação interativa do enredo. Ele também pode redefinir os limites do eixo: observe que o segundo gráfico tem os ticks que solicitamos, incluindo aqueles que estão bem fora dos limites de visualização automática.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
axs[1].xaxis.set_ticks(np.arange(0., 8.1, 2.))
plt.show()
introdução de texto

É claro que podemos corrigir isso após o fato, mas destaca uma fraqueza de codificar os ticks. Este exemplo também altera o formato dos ticks:

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
# list comprehension to get all tick labels...
tickla = [f'{tick:1.2f}' for tick in ticks]
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_ticklabels(tickla)
axs[1].set_xlim(axs[0].get_xlim())
plt.show()
introdução de texto

Localizadores e Formatadores de Marcas #

Em vez de fazer uma lista de todos os ticklabels, poderíamos ter usado matplotlib.ticker.StrMethodFormatter(string de formato de novo estilo str.format() ) ou matplotlib.ticker.FormatStrFormatter(string de formato '%' de estilo antigo) e passá-lo para o arquivo ax.xaxis. A matplotlib.ticker.StrMethodFormattertambém pode ser criado passando a strsem ter que criar explicitamente o formatador.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
ticks = np.arange(0., 8.1, 2.)
axs[1].xaxis.set_ticks(ticks)
axs[1].xaxis.set_major_formatter('{x:1.1f}')
axs[1].set_xlim(axs[0].get_xlim())
plt.show()
introdução de texto

E é claro que poderíamos ter usado um localizador não padrão para definir os locais dos ticks. Observe que ainda passamos os valores do tick, mas a correção do limite x usada acima não é necessária.

fig, axs = plt.subplots(2, 1, figsize=(5, 3), tight_layout=True)
axs[0].plot(x1, y1)
axs[1].plot(x1, y1)
locator = matplotlib.ticker.FixedLocator(ticks)
axs[1].xaxis.set_major_locator(locator)
axs[1].xaxis.set_major_formatter({x}°')
plt.show()
introdução de texto

O formatador padrão é matplotlib.ticker.MaxNLocatorchamado como A palavra-chave steps contém uma lista de múltiplos que podem ser usados ​​para valores de escala. ou seja, neste caso, 2, 4, 6 seriam ticks aceitáveis, assim como 20, 40, 60 ou 0,2, 0,4, 0,6. No entanto, 3, 6, 9 não seriam aceitáveis ​​porque 3 não aparece na lista de etapas.ticker.MaxNLocator(self, nbins='auto', steps=[1, 2, 2.5, 5, 10])

nbins=autousa um algoritmo para determinar quantos tiques serão aceitáveis ​​com base no comprimento do eixo. nbins=4O tamanho da fonte do ticklabel é levado em consideração, mas o comprimento da string do tick não é (porque ainda não é conhecido). trama de mão.

fig, axs = plt.subplots(2, 2, figsize=(8, 5), tight_layout=True)
for n, ax in enumerate(axs.flat):
    ax.plot(x1*10., y1)

formatter = matplotlib.ticker.FormatStrFormatter('%1.1f')
locator = matplotlib.ticker.MaxNLocator(nbins='auto', steps=[1, 4, 10])
axs[0, 1].xaxis.set_major_locator(locator)
axs[0, 1].xaxis.set_major_formatter(formatter)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.AutoLocator()
axs[1, 0].xaxis.set_major_formatter(formatter)
axs[1, 0].xaxis.set_major_locator(locator)

formatter = matplotlib.ticker.FormatStrFormatter('%1.5f')
locator = matplotlib.ticker.MaxNLocator(nbins=4)
axs[1, 1].xaxis.set_major_formatter(formatter)
axs[1, 1].xaxis.set_major_locator(locator)

plt.show()
introdução de texto

Por fim, podemos especificar funções para o formatador usando matplotlib.ticker.FuncFormatter. Além disso, como matplotlib.ticker.StrMethodFormatter, passar uma função criará automaticamente um matplotlib.ticker.FuncFormatter.

def formatoddticks(x, pos):
    """Format odd tick positions."""
    if x % 2:
        return f'{x:1.2f}'
    else:
        return ''


fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.plot(x1, y1)
locator = matplotlib.ticker.MaxNLocator(nbins=6)
ax.xaxis.set_major_formatter(formatoddticks)
ax.xaxis.set_major_locator(locator)

plt.show()
introdução de texto

Datetics #

Matplotlib pode aceitar datetime.datetimee numpy.datetime64 objetos como argumentos de plotagem. Datas e horas requerem formatação especial, que muitas vezes pode se beneficiar da intervenção manual. Para ajudar, as datas possuem Localizadores e Formatadores especiais, definidos no matplotlib.datesmódulo.

Um exemplo simples é o seguinte. Observe como temos que girar os rótulos dos ticks para que eles não se sobreponham.

import datetime

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
base = datetime.datetime(2017, 1, 1, 0, 0, 1)
time = [base + datetime.timedelta(days=x) for x in range(len(x1))]

ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
introdução de texto

Podemos passar um formato para matplotlib.dates.DateFormatter. Observe também que o dia 29 e o próximo mês estão muito próximos. Podemos corrigir isso usando a dates.DayLocatorclasse, que nos permite especificar uma lista de dias do mês a ser usada. Formatadores semelhantes são listados no matplotlib.dates módulo.

import matplotlib.dates as mdates

locator = mdates.DayLocator(bymonthday=[1, 15])
formatter = mdates.DateFormatter('%b %d')

fig, ax = plt.subplots(figsize=(5, 3), tight_layout=True)
ax.xaxis.set_major_locator(locator)
ax.xaxis.set_major_formatter(formatter)
ax.plot(time, y1)
ax.tick_params(axis='x', rotation=70)
plt.show()
introdução de texto

Legendas e Anotações #

Tempo total de execução do script: ( 0 minutos 5,998 segundos)

Galeria gerada por Sphinx-Gallery