real - matplotlib python
Python: la leyenda se superpone con el gráfico circular (1)
La respuesta corta es: Puede usar los argumentos de bbox_to_anchor
loc
, bbox_to_anchor
y adicionalmente bbox_transform
y mode
, para posicionar la leyenda en un eje o figura.
Paso 1: Asegúrate de que se necesita una leyenda.
En muchos casos, no es necesaria ninguna leyenda y la información puede inferirse por el contexto o el color directamente:
Si de hecho la trama no puede vivir sin una leyenda, continúe con el paso 2.
Paso 2: Asegúrate de que se necesita un gráfico circular.
En muchos casos, los gráficos circulares no son la mejor forma de transmitir información.
Si la necesidad de un gráfico circular se determina inequívocamente, procedamos a colocar la leyenda.
Colocando la leyenda
plt.legend()
tiene dos argumentos principales para determinar la posición de la leyenda. El argumento más importante y en sí mismo suficiente es el loc
.
Por ejemplo, plt.legend(loc="upper left")
colocó la leyenda de modo que se asiente en la esquina superior izquierda de su cuadro delimitador. Si no se especifica ningún argumento adicional, este cuadro delimitador será el de los ejes completos.
Sin embargo, podemos especificar nuestro propio cuadro delimitador utilizando el argumento bbox_to_anchor
. Si bbox_to_anchor
tiene una tupla de 2, por ejemplo, bbox_to_anchor=(1,1)
, significa que el cuadro delimitador se encuentra en la esquina superior derecha de los ejes y no tiene extensión. Luego actúa como un punto relativo al cual la leyenda se colocará de acuerdo con el argumento loc
. Luego se expandirá desde el cuadro delimitador de tamaño cero. Por ejemplo, si loc
es "upper left"
, la esquina superior izquierda de la leyenda está en la posición (1,1) y la leyenda se expandirá hacia la derecha y hacia abajo.
Este concepto se usa para la trama anterior, que nos dice la impactante verdad sobre el sesgo en las elecciones de Miss Universo.
import matplotlib.pyplot as plt
import matplotlib.patches
total = [100]
labels = ["Earth", "Mercury", "Venus", "Mars", "Jupiter", "Saturn",
"Uranus", "Neptune", "Pluto *"]
plt.title(''Origin of Miss Universe since 1952'')
plt.gca().axis("equal")
pie = plt.pie(total, startangle=90, colors=[plt.cm.Set3(0)],
wedgeprops = { ''linewidth'': 2, "edgecolor" :"k" })
handles = []
for i, l in enumerate(labels):
handles.append(matplotlib.patches.Patch(color=plt.cm.Set3((i)/8.), label=l))
plt.legend(handles,labels, bbox_to_anchor=(0.85,1.025), loc="upper left")
plt.gcf().text(0.93,0.04,"* out of competition since 2006", ha="right")
plt.subplots_adjust(left=0.1, bottom=0.1, right=0.75)
Para que la leyenda no exceda la figura, usamos plt.subplots_adjust
para obtener más espacio entre el borde de la figura y el eje, que luego puede ser tomado por la leyenda.
También existe la opción de usar un 4-tuple a bbox_to_anchor
. Cómo se usa o interpreta esto se detalla en esta pregunta: ¿Qué significa un argumento de tupla de 4 elementos para ''bbox_to_anchor'' en matplotlib?
y uno puede entonces usar el argumento mode="expand"
para hacer que la leyenda encaje en el cuadro delimitador especificado.
Hay algunas alternativas útiles a este enfoque:
Usar coordenadas de figura
En lugar de especificar la posición de la leyenda en las coordenadas de los ejes, se pueden usar las coordenadas de las figuras. La ventaja es que esto permitirá simplemente colocar la leyenda en una esquina de la figura sin ajustar gran parte del resto. Para este fin, uno usaría el argumento bbox_transform
y le suministraría la transformación de figura. Las coordenadas dadas a bbox_to_anchor
se interpretan entonces como coordenadas de figura.
plt.legend(pie[0],labels, bbox_to_anchor=(1,0), loc="lower right",
bbox_transform=plt.gcf().transFigure)
Aquí (1,0)
es la esquina inferior derecha de la figura. Debido a los espacios predeterminados entre los ejes y el borde de la figura, esto es suficiente para colocar la leyenda de modo que no se superponga con el pie.
En otros casos, aún podría ser necesario adaptar esos espacios de manera que no se vea superposición, por ejemplo
title = plt.title(''What slows down my computer'')
title.set_ha("left")
plt.gca().axis("equal")
pie = plt.pie(total, startangle=0)
labels=["Trojans", "Viruses", "Too many open tabs", "The anti-virus software"]
plt.legend(pie[0],labels, bbox_to_anchor=(1,0.5), loc="center right", fontsize=10,
bbox_transform=plt.gcf().transFigure)
plt.subplots_adjust(left=0.0, bottom=0.1, right=0.45)
Guardar el archivo con bbox_inches="tight"
Ahora puede haber casos en los que estamos más interesados en la figura guardada que en lo que se muestra en la pantalla. Podemos simplemente posicionar la leyenda en el borde de la figura, como
pero luego bbox_inches="tight"
usando bbox_inches="tight"
para savefig
,
plt.savefig("output.png", bbox_inches="tight")
Esto creará una figura más grande, que se asienta alrededor del contenido del lienzo:
Aquí se presenta un enfoque sofisticado, que permite colocar la leyenda dentro de la figura, sin cambiar el tamaño de la figura: Creación de la figura con el tamaño exacto y sin relleno (y la leyenda fuera de los ejes)
Usando subtramas
Una alternativa es usar subparcelas para reservar espacio para la leyenda. En este caso, una subtrama podría tomar el gráfico circular, otra subtrama contendría la leyenda. Esto se muestra a continuación.
fig = plt.figure(4, figsize=(3,3))
ax = fig.add_subplot(211)
total = [4,3,2,81]
labels = ["tough working conditions", "high risk of accident",
"harsh weather", "it''s not allowed to watch DVDs"]
ax.set_title(''What people know about oil rigs'')
ax.axis("equal")
pie = ax.pie(total, startangle=0)
ax2 = fig.add_subplot(212)
ax2.axis("off")
ax2.legend(pie[0],labels, loc="center")
Usando matplotlib en python. La leyenda se superpone con mi gráfico circular. Intenté varias opciones para "loc" como "mejor", 1,2,3 ... pero fue en vano. ¿Alguna sugerencia acerca de cómo mencionar exactamente la posición de la leyenda (como dar relleno de los límites del gráfico circular) o al menos asegurarse de que no se superponga?