Colocando a legenda ( bbox_to_anchor
)
Uma legenda é posicionada dentro da caixa delimitadora dos eixos usando o loc
argumento para plt.legend
.
Por exemplo, loc="upper right"
coloca a legenda no canto superior direito da caixa delimitadora, que por padrão se estende de (0,0)
para (1,1)
nas coordenadas dos eixos (ou na notação da caixa delimitadora (x0,y0, width, height)=(0,0,1,1)
).
Para colocar a legenda fora da caixa delimitadora dos eixos, pode-se especificar uma tupla (x0,y0)
de coordenadas dos eixos no canto inferior esquerdo da legenda.
plt.legend(loc=(1.04,0))
No entanto, uma abordagem mais versátil seria especificar manualmente a caixa delimitadora na qual a legenda deve ser colocada, usando o bbox_to_anchor
argumento Pode-se restringir-se a fornecer apenas a (x0,y0)
parte da bbox. Isso cria uma caixa de amplitude zero, da qual a legenda será expandida na direção fornecida pelo loc
argumento. Por exemplo
plt.legend (bbox_to_anchor = (1.04,1), loc = "superior esquerdo")
coloca a legenda fora dos eixos, de modo que o canto superior esquerdo da legenda esteja na posição (1.04,1)
nas coordenadas dos eixos.
Outros exemplos são dados abaixo, onde, adicionalmente, a interacção entre diferentes argumentos semelhantes mode
e ncols
são mostrados.
l1 = plt.legend(bbox_to_anchor=(1.04,1), borderaxespad=0)
l2 = plt.legend(bbox_to_anchor=(1.04,0), loc="lower left", borderaxespad=0)
l3 = plt.legend(bbox_to_anchor=(1.04,0.5), loc="center left", borderaxespad=0)
l4 = plt.legend(bbox_to_anchor=(0,1.02,1,0.2), loc="lower left",
mode="expand", borderaxespad=0, ncol=3)
l5 = plt.legend(bbox_to_anchor=(1,0), loc="lower right",
bbox_transform=fig.transFigure, ncol=3)
l6 = plt.legend(bbox_to_anchor=(0.4,0.8), loc="upper right")
Detalhes sobre como interpretar o argumento de 4 tuplas bbox_to_anchor
, como em l4
, podem ser encontrados nesta pergunta . O mode="expand"
expande a legenda horizontalmente dentro da caixa delimitadora fornecida pela 4-tupla. Para uma legenda verticalmente expandida, consulte esta pergunta .
Às vezes, pode ser útil especificar a caixa delimitadora nas coordenadas da figura em vez das coordenadas dos eixos. Isso é mostrado no exemplo l5
acima, onde o bbox_transform
argumento é usado para colocar a legenda no canto inferior esquerdo da figura.
Pós-processamento
Colocar a legenda fora dos eixos geralmente leva à situação indesejada de que está completamente ou parcialmente fora da tela da figura.
As soluções para esse problema são:
Ajustar os parâmetros da subparcela
É possível ajustar os parâmetros da subparcela, para que os eixos ocupem menos espaço dentro da figura (e, portanto, deixem mais espaço para a legenda) usando plt.subplots_adjust
. Por exemplo
plt.subplots_adjust(right=0.7)
deixa 30% de espaço no lado direito da figura, onde se pode colocar a legenda.
Layout apertado
Usando plt.tight_layout
Permite ajustar automaticamente os parâmetros da subparcela, de modo que os elementos da figura fiquem firmes nas bordas da figura. Infelizmente, a legenda não é levada em consideração nesse automatismo, mas podemos fornecer uma caixa retangular na qual toda a área de subtrama (incluindo etiquetas) se encaixará.
plt.tight_layout(rect=[0,0,0.75,1])
Salvando a figura combbox_inches = "tight"
O argumento bbox_inches = "tight"
to plt.savefig
pode ser usado para salvar a figura, de modo que todos os artistas na tela (incluindo a legenda) se encaixem na área salva. Se necessário, o tamanho da figura é ajustado automaticamente.
plt.savefig("output.png", bbox_inches="tight")
- ajuste automático dos parâmetros de subparcela
Uma maneira de ajustar automaticamente a posição da subparcela de forma que a legenda caiba dentro da tela sem alterar o tamanho da figura pode ser encontrada nesta resposta: Criando figura com tamanho exato e sem preenchimento (e legenda fora dos eixos)
Comparação entre os casos discutidos acima:
Alternativas
Uma legenda da figura
Pode-se usar uma legenda para a figura em vez dos eixos matplotlib.figure.Figure.legend
,. Isso se tornou especialmente útil para a versão matplotlib> = 2.1, onde nenhum argumento especial é necessário
fig.legend(loc=7)
para criar uma legenda para todos os artistas nos diferentes eixos da figura. A legenda é colocada usando o loc
argumento, semelhante à maneira como é colocada dentro de um eixo, mas em referência a toda a figura - portanto, ela estará fora dos eixos um pouco automaticamente. O que resta é ajustar as subparcelas para que não haja sobreposição entre a legenda e os eixos. Aqui, o ponto "Ajustar os parâmetros da subparcela" acima será útil. Um exemplo:
import numpy as np
import matplotlib.pyplot as plt
x = np.linspace(0,2*np.pi)
colors=["#7aa0c4","#ca82e1" ,"#8bcd50","#e18882"]
fig, axes = plt.subplots(ncols=2)
for i in range(4):
axes[i//2].plot(x,np.sin(x+i), color=colors[i],label="y=sin(x+{})".format(i))
fig.legend(loc=7)
fig.tight_layout()
fig.subplots_adjust(right=0.75)
plt.show()
Legenda dentro dos eixos de subparcela dedicados
Uma alternativa ao uso bbox_to_anchor
seria colocar a legenda em seus eixos de subparcela dedicados ( lax
). Como a subparcela da legenda deve ser menor que a plotagem, podemos usar gridspec_kw={"width_ratios":[4,1]}
na criação dos eixos. Podemos ocultar os eixos, lax.axis("off")
mas ainda assim inserir uma legenda. Os identificadores e etiquetas da legenda precisam ser obtidos da plotagem real via h,l = ax.get_legend_handles_labels()
e, em seguida, podem ser fornecidos à legenda na lax
subparcela lax.legend(h,l)
,. Um exemplo completo está abaixo.
import matplotlib.pyplot as plt
plt.rcParams["figure.figsize"] = 6,2
fig, (ax,lax) = plt.subplots(ncols=2, gridspec_kw={"width_ratios":[4,1]})
ax.plot(x,y, label="y=sin(x)")
....
h,l = ax.get_legend_handles_labels()
lax.legend(h,l, borderaxespad=0)
lax.axis("off")
plt.tight_layout()
plt.show()
Isso produz um gráfico visualmente bastante semelhante ao gráfico acima:
Também podemos usar os primeiros eixos para colocar a legenda, mas usar os bbox_transform
eixos da legenda,
ax.legend(bbox_to_anchor=(0,0,1,1), bbox_transform=lax.transAxes)
lax.axis("off")
Nesta abordagem, não precisamos obter os identificadores de legenda externamente, mas precisamos especificar o bbox_to_anchor
argumento.
Outras leituras e notas:
- Considere o guia de legendas do matplotlib com alguns exemplos de outras coisas que você deseja fazer com as lendas.
- Algum código de exemplo para colocar legendas para gráficos de pizza pode ser encontrado diretamente na resposta a esta pergunta: Python - Legenda se sobrepõe ao gráfico de pizza
- O
loc
argumento pode usar números em vez de strings, o que torna as chamadas mais curtas, no entanto, elas não são mapeadas de maneira muito intuitiva. Aqui está o mapeamento para referência: