Tengo una serie de 20 tramas (no subtramas) para hacer en una sola figura. Quiero que la leyenda esté fuera de la caja. Al mismo tiempo, no quiero cambiar los ejes, ya que el tamaño de la figura se reduce. Amablemente ayúdenme para las siguientes consultas:
- Quiero mantener el cuadro de leyenda fuera del área de la trama. (Quiero que la leyenda esté afuera en el lado derecho del área de la trama).
- ¿Hay alguna forma de reducir el tamaño de fuente del texto dentro del cuadro de leyenda, de modo que el tamaño del cuadro de leyenda sea pequeño.
python
matplotlib
legend
pottigopi
fuente
fuente
https://stackoverflow.com/a/43439132/52074
. ¡Y lo hace con dos líneas de código! la respuesta votada +1200 también es buena, pero me pareció menos genérica.Respuestas:
Puede hacer que el texto de la leyenda sea más pequeño creando propiedades de fuente:
fuente
plot1
en esta respuesta?legend
en esta respuesta?plt.legend(fontsize='small')
Hay varias formas de hacer lo que quieres. Para agregar a lo que ya dijeron @inalis y @Navi, puede usar el
bbox_to_anchor
argumento de la palabra clave para colocar la leyenda parcialmente fuera de los ejes y / o disminuir el tamaño de la fuente.Antes de considerar disminuir el tamaño de la fuente (lo que puede hacer que las cosas sean muy difíciles de leer), intenta jugar colocando la leyenda en diferentes lugares:
Entonces, comencemos con un ejemplo genérico:
Si hacemos lo mismo, pero usamos el
bbox_to_anchor
argumento de la palabra clave, podemos cambiar la leyenda ligeramente fuera de los límites de los ejes:Del mismo modo, puede hacer que la leyenda sea más horizontal y / o ponerla en la parte superior de la figura (también estoy girando en las esquinas redondeadas y una simple sombra paralela):
Alternativamente, puede reducir el ancho del gráfico actual y colocar la leyenda completamente fuera del eje de la figura (nota: si usa tight_layout () , entonces omita ax.set_position ():
Y de manera similar, puede reducir la trama verticalmente y colocar una leyenda horizontal en la parte inferior:
Echa un vistazo a la guía de leyenda matplotlib . También puedes echarle un vistazo
plt.figlegend()
.fuente
bbox_to_anchor
es una tupla de 4 flotadores (x, y, ancho, altura de la caja), o una tupla de 2 flotadores (x, y) en ejes normalizados coordenadas ".legend = ax.legend()
y más tardefig.savefig(bbox_extra_artists=(legend,))
Colocando la leyenda (
bbox_to_anchor
)Se coloca una leyenda dentro del cuadro delimitador de los ejes utilizando el
loc
argumento toplt.legend
.Por ejemplo,
loc="upper right"
coloca la leyenda en la esquina superior derecha del cuadro delimitador, que de forma predeterminada se extiende desde(0,0)
hasta(1,1)
en las coordenadas de los ejes (o en la notación del cuadro delimitador(x0,y0, width, height)=(0,0,1,1)
).Para colocar la leyenda fuera del cuadro delimitador de ejes, se puede especificar una tupla
(x0,y0)
de coordenadas de ejes de la esquina inferior izquierda de la leyenda.Sin embargo, un enfoque más versátil sería especificar manualmente el cuadro delimitador en el que se debe colocar la leyenda, utilizando el
bbox_to_anchor
argumento. Uno puede restringirse para suministrar solo la(x0,y0)
parte de bbox. Esto crea un cuadro de intervalo cero, fuera del cual la leyenda se expandirá en la dirección dada por elloc
argumento. P.ejcoloca la leyenda fuera de los ejes, de modo que la esquina superior izquierda de la leyenda esté en posición
(1.04,1)
en las coordenadas de los ejes.A continuación se dan más ejemplos, donde además se muestra la interacción entre diferentes argumentos como
mode
yncols
.Los detalles sobre cómo interpretar el argumento de 4 tuplas
bbox_to_anchor
, como enl4
, se pueden encontrar en esta pregunta . Elmode="expand"
expande la leyenda horizontalmente dentro del cuadro delimitador propuesta por el 4-tupla. Para una leyenda expandida verticalmente, vea esta pregunta .A veces puede ser útil especificar el cuadro delimitador en las coordenadas de la figura en lugar de las coordenadas de los ejes. Esto se muestra en el ejemplo
l5
de arriba, donde elbbox_transform
argumento se usa para poner la leyenda en la esquina inferior izquierda de la figura.Postprocesamiento
Habiendo colocado la leyenda fuera de los ejes a menudo conduce a la situación no deseada de que está total o parcialmente fuera del lienzo de la figura.
Las soluciones a este problema son:
Ajuste los parámetros de la subtrama
Uno puede ajustar los parámetros de la subtrama de tal manera que los ejes ocupen menos espacio dentro de la figura (y, por lo tanto, dejen más espacio para la leyenda)
plt.subplots_adjust
. P.ejdeja un 30% de espacio en el lado derecho de la figura, donde se puede colocar la leyenda.
Diseño ajustado
Usando
plt.tight_layout
Permite ajustar automáticamente los parámetros de la subtrama de modo que los elementos de la figura se asienten firmemente contra los bordes de la figura. Desafortunadamente, la leyenda no se tiene en cuenta en este automatismo, pero podemos proporcionar un cuadro rectangular en el que se ajustará toda el área de subtramas (incluidas las etiquetas).Guardar la figura con
bbox_inches = "tight"
El argumento
bbox_inches = "tight"
toplt.savefig
se puede usar para guardar la figura de modo que todos los artistas en el lienzo (incluida la leyenda) quepan en el área guardada. Si es necesario, el tamaño de la figura se ajusta automáticamente.En esta respuesta se puede encontrar una forma de ajustar automáticamente la posición de la subtrama de modo que la leyenda se ajuste dentro del lienzo sin cambiar el tamaño de la figura : Crear una figura con tamaño exacto y sin relleno (y leyenda fuera de los ejes)
Comparación entre los casos discutidos anteriormente:
Alternativas
Una leyenda de la figura
se puede usar una leyenda para la figura en lugar de los ejes,
matplotlib.figure.Figure.legend
. Esto se ha vuelto especialmente útil para matplotlib versión> = 2.1, donde no se necesitan argumentos especialespara crear una leyenda para todos los artistas en los diferentes ejes de la figura. La leyenda se coloca usando el
loc
argumento, similar a cómo se coloca dentro de los ejes, pero en referencia a la figura completa, por lo tanto, estará fuera de los ejes de forma algo automática. Lo que queda es ajustar las subtramas para que no haya superposición entre la leyenda y los ejes. Aquí será útil el punto "Ajustar los parámetros de la subtrama" desde arriba. Un ejemplo:Leyenda dentro de ejes de subtrama dedicados
Una alternativa al uso
bbox_to_anchor
sería colocar la leyenda en sus ejes de subtrama dedicados (lax
). Dado que la subtrama de la leyenda debe ser más pequeña que la trama, podemos usarlagridspec_kw={"width_ratios":[4,1]}
en la creación de ejes. Podemos ocultar los ejeslax.axis("off")
pero todavía poner una leyenda en. Los tiradores de leyenda y etiquetas necesitan obtenida a partir de la trama real a travésh,l = ax.get_legend_handles_labels()
, y luego se puede suministrar a la leyenda en lalax
trama secundaria,lax.legend(h,l)
. Un ejemplo completo está abajo.Esto produce una trama que es visualmente bastante similar a la trama de arriba:
También podríamos usar los primeros ejes para colocar la leyenda, pero usar los
bbox_transform
ejes de la leyenda,En este enfoque, no necesitamos obtener los identificadores de leyenda externamente, pero necesitamos especificar el
bbox_to_anchor
argumento.Lecturas adicionales y notas:
loc
argumento puede tomar números en lugar de cadenas, lo que hace que las llamadas sean más cortas, sin embargo, no están muy intuitivamente asignadas entre sí. Aquí está el mapeo para referencia:fuente
fig.tight_layout
. Si está utilizandoplt.subplots
para crear los ejes, simplemente dele algo comogridspec_kw={'height_ratios': [100, 1]}
(o width_ratios) para que los ejes de la leyenda sean pequeños ... Luegofig.tight_layout()
lo expandirá para que se ajuste. Al menos para matplotlib 3.0.3.Simplemente llame
legend()
después de laplot()
llamada así:Los resultados se verían así:
fuente
Para colocar la leyenda fuera del área de trazado, use
loc
ybbox_to_anchor
palabras clave delegend()
. Por ejemplo, el siguiente código colocará la leyenda a la derecha del área de trazado:Para obtener más información, consulte la guía de la leyenda.
fuente
plt.tight_layout()
?Respuesta corta: puedes usar
bbox_to_anchor
+bbox_extra_artists
+bbox_inches='tight'
.Respuesta más larga: puede usar
bbox_to_anchor
para especificar manualmente la ubicación del cuadro de leyenda, como han señalado otras personas en las respuestas.Sin embargo, el problema habitual es que el cuadro de leyenda está recortado, por ejemplo:
Para evitar que el cuadro de leyenda se recorte, cuando guarde la figura, puede usar los parámetros
bbox_extra_artists
ybbox_inches
solicitarsavefig
incluir elementos recortados en la imagen guardada:fig.savefig('image_output.png', bbox_extra_artists=(lgd,), bbox_inches='tight')
Ejemplo (solo cambié la última línea para agregar 2 parámetros
fig.savefig()
):Desearía que matplotlib permitiera nativamente la ubicación externa del cuadro de leyenda como lo hace Matlab :
fuente
bbox_inches='tight'
funciona perfectamente para mí, incluso sin bbox_extra_artistAdemás de todas las excelentes respuestas aquí, las versiones más nuevas de
matplotlib
ypylab
pueden determinar automáticamente dónde colocar la leyenda sin interferir con las tramas , si es posible.¡Esto alejará automáticamente la leyenda de los datos si es posible!
Sin embargo, si no hay lugar para colocar la leyenda sin superponer los datos, entonces querrá probar una de las otras respuestas; usar
loc="best"
nunca pondrá la leyenda fuera de la trama.fuente
Respuesta corta : invoque arrastrable en la leyenda y muévala interactivamente donde desee:
Respuesta larga : si prefiere colocar la leyenda de forma interactiva / manual en lugar de mediante programación, puede alternar el modo arrastrable de la leyenda para poder arrastrarla a donde desee. Verifique el siguiente ejemplo:
fuente
No es exactamente lo que pediste, pero descubrí que es una alternativa para el mismo problema. Haga que la leyenda sea semi-transparente, así:
Haz esto con:
fuente
Como se señaló, también puede colocar la leyenda en la trama, o ligeramente fuera del borde también. Aquí hay un ejemplo usando la API Plotly Python , hecha con un IPython Notebook . Estoy en el equipo
Para comenzar, querrás instalar los paquetes necesarios:
Luego, instale Plotly:
Esto crea su gráfico y le permite tener la leyenda dentro de la trama. El valor predeterminado de la leyenda si no está configurado es colocarlo en el diagrama, como se muestra aquí.
Para una ubicación alternativa, puede alinear estrechamente el borde del gráfico y el borde de la leyenda, y eliminar las líneas de borde para un ajuste más cercano.
Puede mover y cambiar el estilo de la leyenda y el gráfico con código o con la GUI. Para cambiar la leyenda, tiene las siguientes opciones para colocar la leyenda dentro del gráfico asignando valores x e y de <= 1. Por ejemplo:
{"x" : 0,"y" : 0}
- Abajo a la izquierda{"x" : 1, "y" : 0}
-- Abajo a la derecha{"x" : 1, "y" : 1}
-- Parte superior derecha{"x" : 0, "y" : 1}
-- Arriba a la izquierda{"x" :.5, "y" : 0}
-- Parte inferior central{"x": .5, "y" : 1}
-- Centro SuperiorEn este caso, elegimos la esquina superior derecha
legendstyle = {"x" : 1, "y" : 1}
, también descrita en la documentación :fuente
Algo en este sentido me funcionó. Comenzando con un poco de código tomado de Joe, este método modifica el ancho de la ventana para que se ajuste automáticamente a una leyenda a la derecha de la figura.
fuente
mgr.window.wm_geometry(...)
conmgr.window.setFixedWidth(winWidthNew)
.fig.set_size_inches(...)
se encarga del cambio de tamaño que necesita.Vale la pena actualizar esta pregunta, ya que las versiones más nuevas de Matplotlib han hecho que sea mucho más fácil colocar la leyenda fuera de la trama. Produje este ejemplo con la versión Matplotlib
3.1.1
.Los usuarios pueden pasar 2 tuplas de coordenadas al
loc
parámetro para colocar la leyenda en cualquier lugar del cuadro delimitador. El único problema es que debe ejecutarplt.tight_layout()
para obtener matplotlib para volver a calcular las dimensiones de la trama para que la leyenda sea visible:Esto lleva a la siguiente trama:
Referencias
fuente
También puedes intentarlo
figlegend
. Es posible crear una leyenda independiente de cualquier objeto Axes. Sin embargo, es posible que deba crear algunas rutas "ficticias" para asegurarse de que el formato de los objetos se transmite correctamente.fuente
Aquí hay un ejemplo del tutorial matplotlib que se encuentra aquí . Este es uno de los ejemplos más simples, pero agregué transparencia a la leyenda y agregué plt.show () para que pueda pegar esto en el shell interactivo y obtener un resultado:
fuente
La solución que funcionó para mí cuando tenía una gran leyenda era usar un diseño de imagen vacío adicional. En el siguiente ejemplo hice 4 filas y en la parte inferior trazo una imagen con desplazamiento para la leyenda (bbox_to_anchor) en la parte superior, no se corta.
fuente
Aquí hay otra solución, similar a agregar
bbox_extra_artists
ybbox_inches
, donde no tiene que tener sus artistas adicionales en el alcance de susavefig
llamada. Se me ocurrió esto ya que genero la mayor parte de mi trama dentro de las funciones.En lugar de agregar todas sus adiciones al cuadro delimitador cuando desee escribirlas, puede agregarlas con anticipación a los
Figure
artistas de. Usando algo similar a la respuesta de Franck Dernoncourt anterior :Aquí está la trama generada.
fuente
no sé si ya resolvió su problema ... probablemente sí, pero ... simplemente usé la cadena 'afuera' para la ubicación, como en matlab. Importé pylab de matplotlib. ver el código de la siguiente manera:
Haga clic para ver la trama
fuente