katrasnikj
Si agrego un subtítulo a mi figura matplotlib, se superpone con los títulos de la trama secundaria. ¿Alguien sabe cómo solucionarlo fácilmente? Probé el tight_layout()
funcionar, pero solo empeora las cosas.
Ejemplo:
import numpy as np
import matplotlib.pyplot as plt
f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.tight_layout()
plt.show()
Sopa de sopa
Puede ajustar la geometría de la subparcela en el mismo tight_layout
llamar de la siguiente manera:
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
Como se indica en la documentación (https://matplotlib.org/users/tight_layout_guide.html):
tight_layout()
solo considera ticklabels, etiquetas de eje y títulos. Por lo tanto, otros artistas pueden quedar recortados y también pueden superponerse.
-
Funcionó de maravilla, pero ¿cómo ocurre el cambio al especificar el cuadro delimitador? Leí el documento pero no me quedó muy claro. ¡Sería genial si pudieras explicarme! Gracias.
– thepunitsingh
24 de noviembre de 2017 a las 13:22
-
¿podría explicar el significado de cada número en rect? No los vi en el documento.
– steven
13 mayo 2019 a las 21:41
-
@steven ver
tight_layout
documentos:[left, bottom, right, top] in normalized (0, 1) figure coordinates
– sopa de sopa
14 de mayo de 2019 a las 6:58
-
Puede aumentar aún más el espacio entre el subtítulo y los ejes bajando el valor más a la derecha:
tight_layout(rect=[0, 0.03, 1, 0.9])
en vez de0.95
como en la respuesta.– ComFreek
24 de septiembre de 2019 a las 9:17
-
No funcionó dentro de jupyter. Probé diferentes valores para los números, no tuvo ningún efecto
– Aleksejs Fomins
23 de enero de 2020 a las 14:22
Puede ajustar manualmente el espaciado usando plt.subplots_adjust(top=0.85)
:
import numpy as np
import matplotlib.pyplot as plt
f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.subplots_adjust(top=0.85)
plt.show()
-
No puedo creer que en el año 2017 de nuestro señor, esto siga siendo un error de matplotlib.
– palabras para el sabio
13 de enero de 2017 a las 23:28
-
Tenga en cuenta que
subplots_adjust
debe ser llamado después cualquier llamada atight_layout
o no habrá efecto de llamarsubplots_adjust
.– Achal Dave
20 de enero de 2017 a las 18:58
-
@wordsforthewise haz ese 2018 ahora
– vlsd
16 de marzo de 2018 a las 17:23
-
@vlsd Hola desde 2019
– Xiaoyu Lu
23 de septiembre de 2019 a las 4:02
-
2020 aquí y esto sigue siendo un problema
– Tomás Tiotto
21 de junio de 2020 a las 8:38
aseagrama
Una cosa que podrías cambiar en tu código muy fácilmente es el fontsize
está utilizando para los títulos. Sin embargo, voy a asumir que no solo quieres hacer eso.
Algunas alternativas al uso fig.subplots_adjust(top=0.85)
:
Normalmente tight_layout()
hace un trabajo bastante bueno al colocar todo en buenas ubicaciones para que no se superpongan. La razón tight_layout()
no ayuda en este caso es porque tight_layout()
no tiene en cuenta fig.suptitle(). Hay un problema abierto sobre esto en GitHub: https://github.com/matplotlib/matplotlib/issues/829 [closed in 2014 due to requiring a full geometry manager – shifted to https://github.com/matplotlib/matplotlib/issues/1109 ].
Si lees el hilo, hay una solución a tu problema que implica GridSpec
. La clave es dejar algo de espacio en la parte superior de la figura al llamar tight_layout
utilizando el rect
kwarg Para su problema, el código se convierte en:
Usando GridSpec
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure(1)
gs1 = gridspec.GridSpec(1, 2)
ax_list = [fig.add_subplot(ss) for ss in gs1]
ax_list[0].plot(f)
ax_list[0].set_title('Very Long Title 1', fontsize=20)
ax_list[1].plot(g)
ax_list[1].set_title('Very Long Title 2', fontsize=20)
fig.suptitle('Long Suptitle', fontsize=24)
gs1.tight_layout(fig, rect=[0, 0.03, 1, 0.95])
plt.show()
El resultado:
Quizás GridSpec
es un poco exagerado para usted, o su problema real involucrará muchas más tramas secundarias en un lienzo mucho más grande u otras complicaciones. Un truco simple es simplemente usar annotate()
y bloquear las coordenadas a la 'figure fraction'
imitar un suptitle
. Sin embargo, es posible que deba hacer algunos ajustes más finos una vez que eche un vistazo a la salida. Tenga en cuenta que esta segunda solución no no usar tight_layout()
.
Solución más simple (aunque es posible que deba ajustarse)
fig = plt.figure(2)
ax1 = plt.subplot(121)
ax1.plot(f)
ax1.set_title('Very Long Title 1', fontsize=20)
ax2 = plt.subplot(122)
ax2.plot(g)
ax2.set_title('Very Long Title 2', fontsize=20)
# fig.suptitle('Long Suptitle', fontsize=24)
# Instead, do a hack by annotating the first axes with the desired
# string and set the positioning to 'figure fraction'.
fig.get_axes()[0].annotate('Long Suptitle', (0.5, 0.95),
xycoords="figure fraction", ha="center",
fontsize=24
)
plt.show()
El resultado:
[Using Python
2.7.3 (64-bit) and matplotlib
1.2.0]
-
Gracias, si uso la primera solución que sugirió (usando
GridSpec
) ¿Cómo puedo crear subparcelas que comparten ejes? yo suelo usarplt.subplots(N,1, sharex=<>, sharey=<>)
al crear subparcelas, pero el código que publicaste usaadd_subplot
en cambio– Amelio Vázquez-Reina
19/03/2014 a las 15:55
-
Fundición
fig.tight_layout(rect=[0, 0.03, 1, 0.95])
también funciona– sopa de sopa
16 de septiembre de 2015 a las 13:06
-
La segunda solución es la única que funcionó para mí. ¡Gracias!
– Hagbard
9 de marzo de 2020 a las 13:26
bhayley
El diseño ajustado no funciona con subtítulos, pero constrained_layout
lo hace. Consulte esta pregunta Mejore el tamaño/espaciado de subparcelas con muchas subparcelas en matplotlib
Encontré que agregar las subtramas a la vez se veía mejor, es decir
fig, axs = plt.subplots(rows, cols, constrained_layout=True)
# then iterating over the axes to fill in the plots
Pero también se puede agregar en el punto en que se crea la figura:
fig = plt.figure(constrained_layout=True)
ax1 = fig.add_subplot(cols, rows, 1)
# etc
Nota: para hacer que mis subparcelas estén más juntas, también estaba usando
fig.subplots_adjust(wspace=0.05)
y constrained_layout no funciona con esto 🙁
Una solución alternativa y fácil de usar es ajustar las coordenadas del texto del subtítulo en la figura usando el argumento y en la llamada del subtítulo (ver el documentos):
import numpy as np
import matplotlib.pyplot as plt
f = np.random.random(100)
g = np.random.random(100)
fig = plt.figure()
fig.suptitle('Long Suptitle', y=1.05, fontsize=24)
plt.subplot(121)
plt.plot(f)
plt.title('Very Long Title 1', fontsize=20)
plt.subplot(122)
plt.plot(g)
plt.title('Very Long Title 2', fontsize=20)
plt.show()
-
Esta es una gran manera en un cuaderno pero el comando plt.savefig() no obedece. Esta solución aún corta el título en un comando savefig.
– superhéroe
23 de junio de 2016 a las 10:17
herman schaaf
Como mencionaron otros, por defecto, el diseño ajustado no tiene en cuenta los subtítulos. Sin embargo, he encontrado que es posible usar el bbox_extra_artists
argumento para pasar el subtítulo como un cuadro delimitador que debe tenerse en cuenta:
st = fig.suptitle("My Super Title")
plt.savefig("figure.png", bbox_extra_artists=[st], bbox_inches="tight")
Esto obliga al cálculo de diseño ajustado a tomar la suptitle
en cuenta, y se ve como era de esperar.
-
Esta es una gran manera en un cuaderno pero el comando plt.savefig() no obedece. Esta solución aún corta el título en un comando savefig.
– superhéroe
23 de junio de 2016 a las 10:17
aboger
Este sitio web tiene una solución simple para esto con un ejemplo que funcionó para mí. La línea de código que deja espacio para el título es la siguiente:
plt.tight_layout(rect=[0, 0, 1, 0.95])