Nota
Haga clic aquí para descargar el código de ejemplo completo
Guía de diseño restringido #
Cómo usar el diseño restringido para que las tramas se ajusten a la figura de forma limpia.
constrained_layout ajusta automáticamente subtramas y decoraciones como leyendas y barras de colores para que encajen en la ventana de la figura mientras conservan, lo mejor que pueden, el diseño lógico solicitado por el usuario.
constrained_layout es similar a tight_layout , pero usa un solucionador de restricciones para determinar el tamaño de los ejes que les permite encajar.
constrained_layout generalmente debe activarse antes de agregar ejes a una figura. Dos formas de hacerlo son
usando el argumento respectivo para
subplots()
ofigure()
, por ejemplo:plt.subplots(layout="constrained")
activarlo a través de rcParams , como:
plt.rcParams['figure.constrained_layout.use'] = True
Estos se describen en detalle a lo largo de las siguientes secciones.
Ejemplo sencillo #
En Matplotlib, la ubicación de los ejes (incluidas las subparcelas) se especifica en coordenadas de figuras normalizadas. Puede suceder que las etiquetas de los ejes o los títulos (o, a veces, incluso las etiquetas de tick) salgan del área de la figura y, por lo tanto, se recorten.
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
import matplotlib.gridspec as gridspec
import numpy as np
plt.rcParams['savefig.facecolor'] = "0.8"
plt.rcParams['figure.figsize'] = 4.5, 4.
plt.rcParams['figure.max_open_warning'] = 50
def example_plot(ax, fontsize=12, hide_labels=False):
ax.plot([1, 2])
ax.locator_params(nbins=3)
if hide_labels:
ax.set_xticklabels([])
ax.set_yticklabels([])
else:
ax.set_xlabel('x-label', fontsize=fontsize)
ax.set_ylabel('y-label', fontsize=fontsize)
ax.set_title('Title', fontsize=fontsize)
fig, ax = plt.subplots(layout=None)
example_plot(ax, fontsize=24)
Para evitar esto, es necesario ajustar la ubicación de los ejes. Para las subparcelas, esto se puede hacer manualmente ajustando los parámetros de la subparcela usando Figure.subplots_adjust
. Sin embargo, especificar su cifra con el layout="constrained"
argumento de palabra clave # hará el ajuste # automáticamente.
fig, ax = plt.subplots(layout="constrained")
example_plot(ax, fontsize=24)
Cuando tiene varias subparcelas, a menudo ve etiquetas de diferentes ejes que se superponen entre sí.
fig, axs = plt.subplots(2, 2, layout=None)
for ax in axs.flat:
example_plot(ax)
Especificar layout="constrained"
en la llamada a plt.subplots
hace que el diseño se restrinja correctamente.
fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
example_plot(ax)
Barras de color #
Si crea una barra de colores con Figure.colorbar
, debe dejar espacio para ella. constrained_layout
hace esto automáticamente. Tenga en cuenta que si lo especifica use_gridspec=True
, se ignorará porque esta opción está hecha para mejorar el diseño a través de
tight_layout
.
Nota
Para los pcolormesh
argumentos de palabras clave ( pc_kwargs
) usamos un diccionario. A continuación, asignaremos una barra de colores a varios ejes, cada uno de los cuales contiene un ScalarMappable
; especificar la norma y el mapa de colores garantiza que la barra de colores sea precisa para todos los ejes.
arr = np.arange(100).reshape((10, 10))
norm = mcolors.Normalize(vmin=0., vmax=100.)
# see note above: this makes all pcolormesh calls consistent:
pc_kwargs = {'rasterized': True, 'cmap': 'viridis', 'norm': norm}
fig, ax = plt.subplots(figsize=(4, 4), layout="constrained")
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=ax, shrink=0.6)
<matplotlib.colorbar.Colorbar object at 0x7f2cfafb53c0>
Si especifica una lista de ejes (u otro contenedor iterable) en el
ax
argumento de colorbar
, constrained_layout tomará espacio de los ejes especificados.
fig, axs = plt.subplots(2, 2, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
<matplotlib.colorbar.Colorbar object at 0x7f2cfb6eed70>
Si especifica una lista de ejes desde el interior de una cuadrícula de ejes, la barra de colores ocupará el espacio adecuado y dejará un espacio, pero todas las subparcelas seguirán teniendo el mismo tamaño.
fig, axs = plt.subplots(3, 3, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs[1:, ][:, 1], shrink=0.8)
fig.colorbar(im, ax=axs[:, -1], shrink=0.6)
<matplotlib.colorbar.Colorbar object at 0x7f2cdd1a3340>
Subtítulo #
constrained_layout
también puede hacer espacio para suptitle
.
fig, axs = plt.subplots(2, 2, figsize=(4, 4), layout="constrained")
for ax in axs.flat:
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
fig.suptitle('Big Suptitle')
Text(0.5, 0.9895825, 'Big Suptitle')
Leyendas #
Las leyendas se pueden colocar fuera de su eje principal. El diseño restringido está diseñado para manejar esto para Axes.legend()
. Sin embargo, el diseño restringido no maneja las leyendas que se crean a través de
Figure.legend()
(todavía).
fig, ax = plt.subplots(layout="constrained")
ax.plot(np.arange(10), label='This is a plot')
ax.legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
<matplotlib.legend.Legend object at 0x7f2cfb266d70>
Sin embargo, esto robará espacio de un diseño de trama secundaria:
<matplotlib.legend.Legend object at 0x7f2cf99852a0>
Para que una leyenda u otro artista no robe espacio del diseño de la trama secundaria, podemos leg.set_in_layout(False)
. Por supuesto, esto puede significar que la leyenda termine recortada, pero puede ser útil si la trama se llama posteriormente con . Tenga en cuenta, sin embargo, que el estado de la leyenda tendrá que cambiarse nuevamente para que el archivo guardado funcione, y debemos activar manualmente un dibujo si queremos que constrained_layout ajuste el tamaño de los ejes antes de imprimir.fig.savefig('outname.png', bbox_inches='tight')
get_in_layout
fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")
axs[0].plot(np.arange(10))
axs[1].plot(np.arange(10), label='This is a plot')
leg = axs[1].legend(loc='center left', bbox_to_anchor=(0.8, 0.5))
leg.set_in_layout(False)
# trigger a draw so that constrained_layout is executed once
# before we turn it off when printing....
fig.canvas.draw()
# we want the legend included in the bbox_inches='tight' calcs.
leg.set_in_layout(True)
# we don't want the layout to change at this point.
fig.set_layout_engine(None)
try:
fig.savefig('../../doc/_static/constrained_layout_1b.png',
bbox_inches='tight', dpi=100)
except FileNotFoundError:
# this allows the script to keep going if run interactively and
# the directory above doesn't exist
pass
El archivo guardado se parece a:
Una mejor manera de evitar esta incomodidad es simplemente usar el método de leyenda proporcionado por Figure.legend
:
fig, axs = plt.subplots(1, 2, figsize=(4, 2), layout="constrained")
axs[0].plot(np.arange(10))
lines = axs[1].plot(np.arange(10), label='This is a plot')
labels = [l.get_label() for l in lines]
leg = fig.legend(lines, labels, loc='center left',
bbox_to_anchor=(0.8, 0.5), bbox_transform=axs[1].transAxes)
try:
fig.savefig('../../doc/_static/constrained_layout_2b.png',
bbox_inches='tight', dpi=100)
except FileNotFoundError:
# this allows the script to keep going if run interactively and
# the directory above doesn't exist
pass
El archivo guardado se parece a:
Relleno y espaciado #
El relleno entre ejes está controlado en horizontal por w_pad y
wspace , y en vertical por h_pad y hspace . Estos se pueden editar a través de set
. w/h_pad son el espacio mínimo alrededor de los ejes en unidades de pulgadas:
fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0,
wspace=0)
El espacio entre las subparcelas se establece aún más mediante wspace y hspace . Estos se especifican como una fracción del tamaño del grupo de subparcelas como un todo. Si estos valores son más pequeños que w_pad o h_pad , entonces se usan los pads fijos en su lugar. Observe a continuación cómo el espacio en los bordes no cambia con respecto al anterior, pero sí lo hace el espacio entre las subparcelas.
fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.2,
wspace=0.2)
Si hay más de dos columnas, el wspace se comparte entre ellas, por lo que aquí el wspace se divide en 2, con un wspace de 0.1 entre cada columna:
fig, axs = plt.subplots(2, 3, layout="constrained")
for ax in axs.flat:
example_plot(ax, hide_labels=True)
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.2,
wspace=0.2)
GridSpecs también tiene argumentos de palabra clave hspace y wspace opcionales , que se usarán en lugar de los pads establecidos por constrained_layout
:
fig, axs = plt.subplots(2, 2, layout="constrained",
gridspec_kw={'wspace': 0.3, 'hspace': 0.2})
for ax in axs.flat:
example_plot(ax, hide_labels=True)
# this has no effect because the space set in the gridspec trumps the
# space set in constrained_layout.
fig.get_layout_engine().set(w_pad=4 / 72, h_pad=4 / 72, hspace=0.0,
wspace=0.0)
Espaciado con barras de colores #
Las barras de colores se colocan a una distancia de su padre, donde el pad es una fracción del ancho de los padres. El espacio hasta la siguiente subparcela viene dado por w/hspace .
fig, axs = plt.subplots(2, 2, layout="constrained")
pads = [0, 0.05, 0.1, 0.2]
for pad, ax in zip(pads, axs.flat):
pc = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(pc, ax=ax, shrink=0.6, pad=pad)
ax.set_xticklabels([])
ax.set_yticklabels([])
ax.set_title(f'pad: {pad}')
fig.get_layout_engine().set(w_pad=2 / 72, h_pad=2 / 72, hspace=0.2,
wspace=0.2)
rcParams #
Hay cinco rcParams
que se pueden configurar, ya sea en un script o en el matplotlibrc
archivo. Todos tienen el prefijo figure.constrained_layout
:
use : si se debe usar constrained_layout. El valor predeterminado es falso
w_pad , h_pad : Relleno alrededor de objetos de ejes. Flotador que representa pulgadas. El valor predeterminado es 3./72. pulgadas (3 puntos)
wspace , hspace : Espacio entre grupos de subparcelas. Flotante que representa una fracción de los anchos de las subparcelas que se están separando. El valor predeterminado es 0,02.
plt.rcParams['figure.constrained_layout.use'] = True
fig, axs = plt.subplots(2, 2, figsize=(3, 3))
for ax in axs.flat:
example_plot(ax)
Usar con GridSpec #
constrained_layout está diseñado para usarse con subplots()
,
subplot_mosaic()
o
GridSpec()
con
add_subplot()
.
Nótese que en lo que siguelayout="constrained"
plt.rcParams['figure.constrained_layout.use'] = False
fig = plt.figure(layout="constrained")
gs1 = gridspec.GridSpec(2, 1, figure=fig)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
Son posibles diseños gridspec más complicados. Tenga en cuenta que aquí usamos las funciones de conveniencia add_gridspec
y
subgridspec
.
fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2)
gs1 = gs0[0].subgridspec(2, 1)
ax1 = fig.add_subplot(gs1[0])
ax2 = fig.add_subplot(gs1[1])
example_plot(ax1)
example_plot(ax2)
gs2 = gs0[1].subgridspec(3, 1)
for ss in gs2:
ax = fig.add_subplot(ss)
example_plot(ax)
ax.set_title("")
ax.set_xlabel("")
ax.set_xlabel("x-label", fontsize=12)
Text(0.5, 41.33399999999999, 'x-label')
Tenga en cuenta que en lo anterior, las columnas izquierda y derecha no tienen la misma extensión vertical. Si queremos que la parte superior e inferior de las dos cuadrículas se alineen, deben estar en la misma especificación de cuadrícula. Necesitamos hacer esta figura más grande también para que los ejes no colapsen a la altura cero:
fig = plt.figure(figsize=(4, 6), layout="constrained")
gs0 = fig.add_gridspec(6, 2)
ax1 = fig.add_subplot(gs0[:3, 0])
ax2 = fig.add_subplot(gs0[3:, 0])
example_plot(ax1)
example_plot(ax2)
ax = fig.add_subplot(gs0[0:2, 1])
example_plot(ax, hide_labels=True)
ax = fig.add_subplot(gs0[2:4, 1])
example_plot(ax, hide_labels=True)
ax = fig.add_subplot(gs0[4:, 1])
example_plot(ax, hide_labels=True)
fig.suptitle('Overlapping Gridspecs')
Text(0.5, 0.993055, 'Overlapping Gridspecs')
Este ejemplo usa dos gridspecs para que la barra de colores solo pertenezca a un conjunto de pcolors. Observe cómo la columna de la izquierda es más ancha que las dos columnas de la derecha debido a esto. Por supuesto, si quería que las subparcelas tuvieran el mismo tamaño, solo necesitaba una especificación de cuadrícula. Tenga en cuenta que se puede lograr el mismo efecto usando subfigures
.
fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2, figure=fig, width_ratios=[1, 2])
gs_left = gs0[0].subgridspec(2, 1)
gs_right = gs0[1].subgridspec(2, 2)
for gs in gs_left:
ax = fig.add_subplot(gs)
example_plot(ax)
axs = []
for gs in gs_right:
ax = fig.add_subplot(gs)
pcm = ax.pcolormesh(arr, **pc_kwargs)
ax.set_xlabel('x-label')
ax.set_ylabel('y-label')
ax.set_title('title')
axs += [ax]
fig.suptitle('Nested plots using subgridspec')
fig.colorbar(pcm, ax=axs)
<matplotlib.colorbar.Colorbar object at 0x7f2cdf471c30>
En lugar de usar subgridspecs, Matplotlib ahora proporciona subfigures
que también funcionan con constrained_layout
:
fig = plt.figure(layout="constrained")
sfigs = fig.subfigures(1, 2, width_ratios=[1, 2])
axs_left = sfigs[0].subplots(2, 1)
for ax in axs_left.flat:
example_plot(ax)
axs_right = sfigs[1].subplots(2, 2)
for ax in axs_right.flat:
pcm = ax.pcolormesh(arr, **pc_kwargs)
ax.set_xlabel('x-label')
ax.set_ylabel('y-label')
ax.set_title('title')
fig.colorbar(pcm, ax=axs_right)
fig.suptitle('Nested plots using subfigures')
Text(0.5, 0.9895825, 'Nested plots using subfigures')
Configuración manual de las posiciones de los ejes #
Puede haber buenas razones para establecer manualmente una posición de ejes. Una llamada manual a set_position
configurará los ejes para que constrained_layout ya no tenga ningún efecto. (Tenga en cuenta que constrained_layout
todavía deja el espacio para los ejes que se mueve).
fig, axs = plt.subplots(1, 2, layout="constrained")
example_plot(axs[0], fontsize=12)
axs[1].set_position([0.2, 0.2, 0.4, 0.4])
Cuadrículas de ejes de relación de aspecto fija: diseño "comprimido" #
constrained_layout
opera en la grilla de posiciones "originales" para ejes. Sin embargo, cuando los ejes tienen relaciones de aspecto fijas, un lado generalmente se acorta y deja grandes espacios en la dirección acortada. A continuación, los ejes son cuadrados, pero la figura es bastante ancha, por lo que hay un espacio horizontal:
fig, axs = plt.subplots(2, 2, figsize=(5, 3),
sharex=True, sharey=True, layout="constrained")
for ax in axs.flat:
ax.imshow(arr)
fig.suptitle("fixed-aspect plots, layout='constrained'")
Text(0.5, 0.98611, "fixed-aspect plots, layout='constrained'")
Una forma obvia de solucionar esto es hacer que el tamaño de la figura sea más cuadrado, sin embargo, cerrar los espacios exactamente requiere prueba y error. Para cuadrículas simples de ejes que podemos usar layout="compressed"
para hacer el trabajo por nosotros:
fig, axs = plt.subplots(2, 2, figsize=(5, 3),
sharex=True, sharey=True, layout='compressed')
for ax in axs.flat:
ax.imshow(arr)
fig.suptitle("fixed-aspect plots, layout='compressed'")
Text(0.5, 0.98611, "fixed-aspect plots, layout='compressed'")
Apagar manualmente constrained_layout
#
constrained_layout
normalmente ajusta las posiciones de los ejes en cada dibujo de la figura. Si desea obtener el espaciado proporcionado por
constrained_layout
pero no actualizarlo, haga el dibujo inicial y luego llame a fig.set_layout_engine(None)
. Esto es potencialmente útil para animaciones en las que las etiquetas de marca pueden cambiar de longitud.
Tenga en cuenta que constrained_layout
está desactivado para eventos ZOOM
de PAN
GUI para los backends que usan la barra de herramientas. Esto evita que los ejes cambien de posición durante el zoom y la panorámica.
Limitaciones #
Funciones incompatibles #
constrained_layout
funcionará con pyplot.subplot
, pero solo si el número de filas y columnas es el mismo para cada llamada. La razón es que cada llamada a pyplot.subplot
creará una nueva
GridSpec
instancia si la geometría no es la misma, y
constrained_layout
. Así que lo siguiente funciona bien:
fig = plt.figure(layout="constrained")
ax1 = plt.subplot(2, 2, 1)
ax2 = plt.subplot(2, 2, 3)
# third axes that spans both rows in second column:
ax3 = plt.subplot(2, 2, (2, 4))
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
plt.suptitle('Homogenous nrows, ncols')
Text(0.5, 0.9895825, 'Homogenous nrows, ncols')
pero lo siguiente conduce a un diseño pobre:
fig = plt.figure(layout="constrained")
ax1 = plt.subplot(2, 2, 1)
ax2 = plt.subplot(2, 2, 3)
ax3 = plt.subplot(1, 2, 2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
plt.suptitle('Mixed nrows, ncols')
Text(0.5, 0.9895825, 'Mixed nrows, ncols')
Del mismo modo,
subplot2grid
funciona con la misma limitación de que nrows y ncols no pueden cambiar para que el diseño se vea bien.
fig = plt.figure(layout="constrained")
ax1 = plt.subplot2grid((3, 3), (0, 0))
ax2 = plt.subplot2grid((3, 3), (0, 1), colspan=2)
ax3 = plt.subplot2grid((3, 3), (1, 0), colspan=2, rowspan=2)
ax4 = plt.subplot2grid((3, 3), (1, 2), rowspan=2)
example_plot(ax1)
example_plot(ax2)
example_plot(ax3)
example_plot(ax4)
fig.suptitle('subplot2grid')
Text(0.5, 0.9895825, 'subplot2grid')
Otras advertencias #
constrained_layout
solo considera ticklabels, etiquetas de eje, títulos y leyendas. Por lo tanto, otros artistas pueden quedar recortados y también pueden superponerse.Asume que el espacio adicional necesario para las etiquetas de marca, las etiquetas de los ejes y los títulos es independiente de la ubicación original de los ejes. Esto suele ser cierto, pero hay casos raros en los que no lo es.
Existen pequeñas diferencias en la forma en que los backends manejan las fuentes de representación, por lo que los resultados no serán idénticos en píxeles.
Un artista que use coordenadas de ejes que se extiendan más allá del límite de los ejes dará como resultado diseños inusuales cuando se agreguen a los ejes. Esto se puede evitar agregando el artista directamente al
Figure
uso deadd_artist()
. VeaConnectionPatch
un ejemplo.
Depuración #
El diseño restringido puede fallar de formas un tanto inesperadas. Debido a que utiliza un solucionador de restricciones, el solucionador puede encontrar soluciones que son matemáticamente correctas, pero que no son en absoluto lo que el usuario quiere. El modo de falla habitual es que todos los tamaños colapsen a su valor más pequeño permitido. Si esto sucede, es por una de dos razones:
No había espacio suficiente para los elementos que solicitaba dibujar.
Hay un error, en cuyo caso, abra un problema en https://github.com/matplotlib/matplotlib/issues .
Si hay un error, informe con un ejemplo independiente que no requiera datos externos o dependencias (que no sean numpy).
Notas sobre el algoritmo #
El algoritmo para la restricción es relativamente sencillo, pero tiene cierta complejidad debido a las formas complejas en que podemos diseñar una figura.
El diseño en Matplotlib se lleva a cabo con gridspecs a través de la GridSpec
clase. Una gridspec es una división lógica de la figura en filas y columnas, con el ancho relativo de los ejes en esas filas y columnas establecido por width_ratios y height_ratios .
En constrained_layout, cada gridspec tiene un layoutgrid asociado. La cuadrícula de diseño tiene una serie de variables para cada columna left
y variables para cada fila, y además tiene un margen para cada uno de los lados izquierdo, derecho, inferior y superior. En cada fila, los márgenes inferior/superior se amplían hasta que se acomodan todos los decoradores de esa fila. Del mismo modo para las columnas y los márgenes izquierdo/derecho.right
bottom
top
Caso simple: uno Ejes #
Para un solo eje, el diseño es sencillo. Hay una cuadrícula de diseño principal para la figura que consta de una columna y una fila, y una cuadrícula de diseño secundaria para la especificación de cuadrícula que contiene los ejes, nuevamente compuesta por una fila y una columna. Se hace espacio para las "decoraciones" a cada lado de los ejes. En el código, esto se logra mediante las entradas
do_constrained_layout()
como:
gridspec._layoutgrid[0, 0].edit_margin_min('left',
-bbox.x0 + pos.x0 + w_pad)
dónde bbox
está el cuadro delimitador estrecho de los ejes y pos
su posición. Nótese cómo los cuatro márgenes abarcan las decoraciones de los ejes.
from matplotlib._layoutgrid import plot_children
fig, ax = plt.subplots(layout="constrained")
example_plot(ax, fontsize=24)
plot_children(fig)
Caso simple: dos ejes #
Cuando hay varios ejes, sus diseños están vinculados de forma sencilla. En este ejemplo, los ejes izquierdos tienen decoraciones mucho más grandes que los derechos, pero comparten un margen inferior, lo suficientemente grande como para acomodar la etiqueta x más grande. Lo mismo con el margen superior compartido. Los márgenes izquierdo y derecho no se comparten y, por lo tanto, se permite que sean diferentes.
fig, ax = plt.subplots(1, 2, layout="constrained")
example_plot(ax[0], fontsize=32)
example_plot(ax[1], fontsize=8)
plot_children(fig)
Dos ejes y barra de colores #
Una barra de colores es simplemente otro elemento que expande el margen de la celda principal de la cuadrícula de diseño:
Barra de colores asociada con un Gridspec #
Si una barra de colores pertenece a más de una celda de la cuadrícula, entonces crea un margen más grande para cada una:
fig, axs = plt.subplots(2, 2, layout="constrained")
for ax in axs.flat:
im = ax.pcolormesh(arr, **pc_kwargs)
fig.colorbar(im, ax=axs, shrink=0.6)
plot_children(fig)
Ejes de tamaño desigual #
Hay dos formas de hacer que los ejes tengan un tamaño desigual en un diseño de Gridspec, ya sea especificándolos para cruzar filas o columnas de Gridspecs, o especificando proporciones de ancho y alto.
El primer método se utiliza aquí. Tenga en cuenta que el centro top
y
los bottom
márgenes no se ven afectados por la columna de la izquierda. Esta es una decisión consciente del algoritmo y conduce al caso en el que los dos ejes de la derecha tienen la misma altura, pero no es la mitad de la altura de los ejes de la izquierda. Esto es consistente con la forma en que gridspec
funciona sin un diseño restringido.
fig = plt.figure(layout="constrained")
gs = gridspec.GridSpec(2, 2, figure=fig)
ax = fig.add_subplot(gs[:, 0])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[0, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
ax = fig.add_subplot(gs[1, 1])
im = ax.pcolormesh(arr, **pc_kwargs)
plot_children(fig)
Un caso que requiere sutileza es si los márgenes no tienen artistas que restrinjan su ancho. En el caso siguiente, el margen derecho de la columna 0 y el margen izquierdo de la columna 3 no tienen artistas de margen para establecer su ancho, por lo que tomamos el ancho máximo de los anchos de margen que tienen artistas. Esto hace que todos los ejes tengan el mismo tamaño:
fig = plt.figure(layout="constrained")
gs = fig.add_gridspec(2, 4)
ax00 = fig.add_subplot(gs[0, 0:2])
ax01 = fig.add_subplot(gs[0, 2:])
ax10 = fig.add_subplot(gs[1, 1:3])
example_plot(ax10, fontsize=14)
plot_children(fig)
plt.show()
Tiempo total de ejecución del script: (0 minutos 18,885 segundos)