Eu tenho uma série de 20 gráficos (não sub-gráficos) a serem feitos em uma única figura. Eu quero que a lenda esteja fora da caixa. Ao mesmo tempo, não quero alterar os eixos, pois o tamanho da figura é reduzido. Por favor, me ajude para as seguintes perguntas:
- Quero manter a caixa de legenda fora da área de plotagem. (Eu quero que a legenda esteja do lado de fora do lado direito da área da plotagem).
- Existe alguma maneira de reduzir o tamanho da fonte do texto dentro da caixa de legenda, para que o tamanho da caixa de legenda seja pequeno.
python
matplotlib
legend
pottigopi
fonte
fonte
https://stackoverflow.com/a/43439132/52074
. e faz isso com duas linhas de código! a resposta +1200 upvoted também é boa, mas eu achei que era menos genérico.Respostas:
Você pode diminuir o texto da legenda criando propriedades de fonte:
fonte
plot1
nesta resposta?legend
nesta resposta?plt.legend(fontsize='small')
Existem várias maneiras de fazer o que você deseja. Para adicionar o que @inalis e @Navi já disseram, você pode usar o
bbox_to_anchor
argumento keyword para colocar a legenda parcialmente fora dos eixos e / ou diminuir o tamanho da fonte.Antes de considerar diminuir o tamanho da fonte (o que pode dificultar bastante a leitura), tente colocar a legenda em locais diferentes:
Então, vamos começar com um exemplo genérico:
Se fizermos a mesma coisa, mas usarmos o
bbox_to_anchor
argumento de palavra - chave, podemos deslocar a legenda ligeiramente fora dos limites dos eixos:Da mesma forma, você pode tornar a legenda mais horizontal e / ou colocá-la no topo da figura (também estou ativando cantos arredondados e uma simples sombra):
Como alternativa, você pode reduzir a largura do gráfico atual e colocar a legenda completamente fora do eixo da figura (nota: se você usar tight_layout () , deixe de fora ax.set_position ():
E de maneira semelhante, você pode reduzir o gráfico verticalmente e colocar a legenda a horizontal na parte inferior:
Dê uma olhada no guia de legendas do matplotlib . Você também pode dar uma olhada
plt.figlegend()
.fonte
bbox_to_anchor
é uma tupla de 4 flutuadores (x, y, largura, altura da bbox) ou uma tupla de 2 flutuadores (x, y) em eixos normalizados coordenadas. "legend = ax.legend()
mais tardefig.savefig(bbox_extra_artists=(legend,))
Colocando a legenda (
bbox_to_anchor
)Uma legenda é posicionada dentro da caixa delimitadora dos eixos usando o
loc
argumento paraplt.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.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 peloloc
argumento. Por exemplocoloca 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
encols
são mostrados.Detalhes sobre como interpretar o argumento de 4 tuplas
bbox_to_anchor
, como eml4
, podem ser encontrados nesta pergunta . Omode="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 obbox_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 exemplodeixa 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á.Salvando a figura com
bbox_inches = "tight"
O argumento
bbox_inches = "tight"
toplt.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.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áriopara 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: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 usargridspec_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 viah,l = ax.get_legend_handles_labels()
e, em seguida, podem ser fornecidos à legenda nalax
subparcelalax.legend(h,l)
,. Um exemplo completo está abaixo.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,Nesta abordagem, não precisamos obter os identificadores de legenda externamente, mas precisamos especificar o
bbox_to_anchor
argumento.Outras leituras e notas:
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:fonte
fig.tight_layout
. Se você estiver usandoplt.subplots
para criar os eixos, dê a ele algo comogridspec_kw={'height_ratios': [100, 1]}
(ou width_ratios) para que os eixos da legenda sejam pequenos ... Em seguidafig.tight_layout()
, ele será expandido para caber. Pelo menos para o matplotlib 3.0.3.Basta ligar para a
legend()
chamada após aplot()
chamada da seguinte maneira:Os resultados seriam algo assim:
fonte
Para colocar a legenda fora da área de plotagem, use
loc
ebbox_to_anchor
palavras - chave delegend()
. Por exemplo, o código a seguir colocará a legenda à direita da área de plotagem:Para mais informações, consulte o guia da legenda
fonte
plt.tight_layout()
?Resposta curta: você pode usar
bbox_to_anchor
+bbox_extra_artists
+bbox_inches='tight'
.Resposta mais longa: você pode usar
bbox_to_anchor
para especificar manualmente o local da caixa da legenda, como algumas pessoas apontaram nas respostas.No entanto, o problema usual é que a caixa de legenda é cortada, por exemplo:
Para impedir que a caixa de legenda seja cortada, ao salvar a figura, você pode usar os parâmetros
bbox_extra_artists
ebbox_inches
solicitarsavefig
a inclusão de elementos cortados na imagem salva:fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')
Exemplo (apenas alterei a última linha para adicionar 2 parâmetros
fig.savefig()
):Desejo que o matplotlib permita nativamente um local externo para a caixa de legenda, como o Matlab :
fonte
bbox_inches='tight'
funciona perfeitamente para mim mesmo sem bbox_extra_artistAlém de todas as excelentes respostas aqui, as versões mais recentes
matplotlib
epylab
podem determinar automaticamente onde colocar a legenda sem interferir nas plotagens , se possível.Isso colocará automaticamente a legenda longe dos dados, se possível!
No entanto, se não houver lugar para colocar a legenda sem sobrepor os dados, tente uma das outras respostas; o uso
loc="best"
nunca colocará a legenda fora da trama.fonte
Resposta curta : chame a legível arrastável e mova-a de forma interativa para onde desejar:
Resposta longa : Se preferir colocar a legenda de maneira interativa / manual, em vez de programaticamente, você pode alternar o modo arrastável da legenda para poder arrastá-la para onde quiser. Veja o exemplo abaixo:
fonte
Não é exatamente o que você pediu, mas eu achei uma alternativa para o mesmo problema. Torne a legenda semi-transparente, da seguinte forma:
Faça isso com:
fonte
Como observado, você também pode colocar a legenda na plotagem, ou um pouco fora dela também. Aqui está um exemplo usando a API Plotly Python , feita com um notebook IPython . Eu estou no time.
Para começar, você desejará instalar os pacotes necessários:
Em seguida, instale o Plotly:
Isso cria seu gráfico e permite que você mantenha a legenda dentro da própria plotagem. O padrão para a legenda, se não estiver definida, é colocá-la na plotagem, conforme mostrado aqui.
Para um posicionamento alternativo, você pode alinhar estreitamente a borda do gráfico e a borda da legenda e remover as linhas da borda para um ajuste mais próximo.
Você pode mover e refazer o estilo da legenda e do gráfico com código ou com a GUI. Para mudar a legenda, você tem as seguintes opções para posicionar a legenda dentro do gráfico, atribuindo valores x e y de <= 1. Por exemplo:
{"x" : 0,"y" : 0}
-- Inferior esquerdo{"x" : 1, "y" : 0}
-- Canto inferior direito{"x" : 1, "y" : 1}
-- Canto superior direito{"x" : 0, "y" : 1}
- Superior esquerdo{"x" :.5, "y" : 0}
- Centro inferior{"x": .5, "y" : 1}
- Centro superiorNesse caso, escolhemos o canto superior direito
legendstyle = {"x" : 1, "y" : 1}
, também descrito na documentação :fonte
Algo nesse sentido funcionou para mim. Começando com um pouco de código retirado de Joe, esse método modifica a largura da janela para ajustar automaticamente uma legenda à direita da figura.
fonte
mgr.window.wm_geometry(...)
pormgr.window.setFixedWidth(winWidthNew)
.fig.set_size_inches(...)
cuida do redimensionamento que você precisa.Vale a pena atualizar essa pergunta, pois as versões mais recentes do Matplotlib tornaram muito mais fácil posicionar a legenda fora da trama. Eu produzi este exemplo com a versão Matplotlib
3.1.1
.Os usuários podem passar duas tuplas de coordenadas para o
loc
parâmetro para posicionar a legenda em qualquer lugar da caixa delimitadora. O único problema é que você precisa executarplt.tight_layout()
para que o matplotlib recompute as dimensões da plotagem para que a legenda fique visível:Isso leva ao seguinte gráfico:
Referências:
fonte
Você também pode tentar
figlegend
. É possível criar uma legenda independente de qualquer objeto Axes. No entanto, pode ser necessário criar alguns caminhos "fictícios" para garantir que a formatação dos objetos seja transmitida corretamente.fonte
Aqui está um exemplo do tutorial matplotlib encontrado aqui . Este é um dos exemplos mais simples, mas adicionei transparência à legenda e adicionei plt.show () para que você possa colar isso no shell interativo e obter um resultado:
fonte
A solução que funcionou para mim quando eu tinha uma lenda enorme foi usar um layout de imagem extra vazio. No exemplo a seguir, criei 4 linhas e na parte inferior plotei a imagem com deslocamento para legenda (bbox_to_anchor) na parte superior, não é cortada.
fonte
Aqui está outra solução, semelhante à adição
bbox_extra_artists
ebbox_inches
, na qual você não precisa ter artistas extras no escopo de suasavefig
ligação. Eu vim com isso desde que eu gere a maior parte do meu enredo dentro de funções.Em vez de adicionar todas as suas adições à caixa delimitadora quando quiser escrevê-las, você poderá adicioná-las antecipadamente aos
Figure
artistas do artista. Usando algo semelhante à resposta de Franck Dernoncourt acima :Aqui está o gráfico gerado.
fonte
não sei se você já resolveu o problema ... provavelmente sim, mas ... simplesmente usei a string 'outside' para o local, como no matlab. Importei o pylab do matplotlib. veja o código da seguinte maneira:
Clique para ver a trama
fonte