Python – La leyenda se superpone con el gráfico circular

Utilizando matplotlib en python. La leyenda se superpone con mi gráfico circular. Probé varias opciones para “loc” como “mejor”, 1,2,3 … pero fue en vano. ¿Alguna sugerencia sobre cómo mencionar exactamente la posición de la leyenda (como el relleno desde los límites del gráfico circular) o al menos asegurarse de que no se superponga?

La respuesta corta es: puede usar los argumentos de bbox_to_anchor loc , bbox_to_anchor y adicionalmente bbox_transform y mode , para colocar la leyenda en un eje o figura.


La versión larga:

Paso 1: Asegurarse de que se necesita una leyenda.

En muchos casos, no se necesita ninguna leyenda y la información se puede inferir por el contexto o el color directamente:

introduzca la descripción de la imagen aquí

introduzca la descripción de la imagen aquí

Si, efectivamente, la ttwig no puede vivir sin una leyenda, continúe con el paso 2.

Paso 2: Asegurándose de que se necesita un gráfico circular.

En muchos casos, los gráficos circulares no son la mejor manera de transmitir información.

introduzca la descripción de la imagen aquí

Si la necesidad de un gráfico circular se determina de manera inequívoca, procederemos a colocar la leyenda.

Colocando la leyenda

plt.legend() tiene dos argumentos principales para determinar la posición de la leyenda. Lo más importante y suficiente en sí mismo es el argumento loc .
Por ejemplo, plt.legend(loc="upper left") coloca la leyenda de manera que se encuentra en la esquina superior izquierda de su cuadro delimitador. Si no se especifica ningún otro argumento, este cuadro delimitador será el eje completo.

Sin embargo, podemos especificar nuestro propio cuadro de delimitación usando el argumento bbox_to_anchor . Si bbox_to_anchor recibe una bbox_to_anchor=(1,1) tupla, por ejemplo, bbox_to_anchor=(1,1) , significa que el cuadro delimitador está ubicado 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á fuera del 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 utiliza para la ttwig anterior, que nos dice la verdad impactante 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 retomado por la leyenda.

También existe la opción de usar una tupla de 4 para bbox_to_anchor . La forma de usar o interpretar esto se detalla en esta pregunta: ¿Qué significa un argumento de tupla de 4 elementos para ‘bbox_to_anchor’ en matplotlib?
y luego se puede usar el argumento mode="expand" para hacer que la leyenda encaje en el cuadro delimitador especificado.

Hay algunas alternativas útiles para este enfoque:

Usando coordenadas de figuras

En lugar de especificar la posición de la leyenda en las coordenadas de los ejes, se pueden usar las coordenadas de la figura. La ventaja es que esto permitirá simplemente colocar la leyenda en una esquina de la figura sin ajustar mucho del rest. 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 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) está la esquina inferior derecha de la figura. Debido a las separaciones predeterminadas entre los ejes y el borde de la figura, esto es suficiente para colocar la leyenda de modo que no se superponga con el pastel.

introduzca la descripción de la imagen aquí

En otros casos, podría ser necesario adaptar esas separaciones de manera que no se vea ninguna 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) 

introduzca la descripción de la imagen aquí

Guardando 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. Entonces podemos simplemente colocar la leyenda en el borde de la figura, así

introduzca la descripción de la imagen aquí

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 canvas:

introduzca la descripción de la imagen aquí

Aquí se presenta un enfoque sofisticado, que permite colocar la leyenda firmemente 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 leyenda fuera de los ejes)

Usando Subplots

Una alternativa es usar subplots para reservar espacio para la leyenda. En este caso, una subplot podría tomar el gráfico circular, otra plot 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") 

introduzca la descripción de la imagen aquí