Nota
Haga clic aquí para descargar el código de ejemplo completo
Organizar varios ejes en una figura #
A menudo, se necesita más de un Hacha en una figura a la vez, generalmente organizadas en una cuadrícula regular. Matplotlib tiene una variedad de herramientas para trabajar con cuadrículas de ejes que han evolucionado a lo largo de la historia de la biblioteca. Aquí discutiremos las herramientas que creemos que los usuarios deberían usar con más frecuencia, las herramientas que sustentan cómo se organizan los ejes y mencionaremos algunas de las herramientas más antiguas.
Nota
Matplotlib usa Axes para referirse al área de dibujo que contiene datos, ejes x e y, marcas, etiquetas, título, etc. Consulte Partes de una figura para obtener más detalles. Otro término que se usa a menudo es "subparcela", que se refiere a un eje que está en una cuadrícula con otros objetos de eje.
Resumen #
Crea combinaciones de ejes en forma de cuadrícula #
subplots
La función principal utilizada para crear figuras y una cuadrícula de ejes. Crea y coloca todos los ejes en la figura a la vez y devuelve una matriz de objetos con identificadores para los ejes en la cuadrícula. ver
Figure.subplots
_
o
subplot_mosaic
Una forma sencilla de crear figuras y una cuadrícula de ejes, con la flexibilidad añadida de que los ejes también pueden abarcar filas o columnas. Los ejes se devuelven en un diccionario etiquetado en lugar de una matriz. Ver también
Figure.subplot_mosaic
y Composición de figuras complejas y semánticas .
A veces es natural tener más de un grupo distinto de cuadrículas de ejes, en cuyo caso Matplotlib tiene el concepto de SubFigure
:
SubFigure
Una figura virtual dentro de una figura.
Herramientas subyacentes #
Subyacentes a estos están el concepto de a GridSpec
y a SubplotSpec
:
GridSpec
Especifica la geometría de la cuadrícula en la que se colocará una subparcela. Es necesario establecer el número de filas y el número de columnas de la cuadrícula. Opcionalmente, se pueden ajustar los parámetros de diseño de la subparcela (p. ej., izquierda, derecha, etc.).
SubplotSpec
Especifica la ubicación de la subparcela en el archivo
GridSpec
.
Agregar ejes individuales a la vez #
Las funciones anteriores crean todos los ejes en una sola llamada de función. También es posible agregar ejes uno a la vez, y así era originalmente como funcionaba Matplotlib. Hacerlo es generalmente menos elegante y flexible, aunque a veces es útil para el trabajo interactivo o para colocar ejes en una ubicación personalizada:
add_axes
Agrega un solo eje en una ubicación especificada por en fracciones del ancho o alto de la figura.
[left, bottom, width, height]
subplot
oFigure.add_subplot
Agrega una única subtrama en una figura, con indexación basada en 1 (heredada de Matlab). Las columnas y las filas se pueden expandir especificando un rango de celdas de cuadrícula.
subplot2grid
Similar a
pyplot.subplot
, pero utiliza la indexación basada en 0 y el corte de dos dimensiones de Python para elegir las celdas.
Métodos de alto nivel para hacer grillas #
Rejilla básica 2x2 #
Podemos crear una cuadrícula básica de ejes de 2 por 2 usando
subplots
. Devuelve una Figure
instancia y una matriz de Axes
objetos. Los objetos Axes se pueden usar para acceder a métodos para colocar artistas en los Axes; aquí usamos annotate
, pero otros ejemplos podrían ser plot
,
pcolormesh
, etc.
import matplotlib.pyplot as plt
import numpy as np
fig, axs = plt.subplots(ncols=2, nrows=2, figsize=(5.5, 3.5),
layout="constrained")
# add an artist, in this case a nice label in the middle...
for row in range(2):
for col in range(2):
axs[row, col].annotate(f'axs[{row}, {col}]', (0.5, 0.5),
transform=axs[row, col].transAxes,
ha='center', va='center', fontsize=18,
color='darkgrey')
fig.suptitle('plt.subplots()')
Text(0.5, 0.9880942857142857, 'plt.subplots()')
Anotaremos muchos ejes, así que encapsulemos la anotación, en lugar de tener ese gran código de anotación cada vez que lo necesitemos:
def annotate_axes(ax, text, fontsize=18):
ax.text(0.5, 0.5, text, transform=ax.transAxes,
ha="center", va="center", fontsize=fontsize, color="darkgrey")
Se puede lograr el mismo efecto con subplot_mosaic
, pero el tipo de retorno es un diccionario en lugar de una matriz, donde el usuario puede dar significados útiles a las claves. Aquí proporcionamos dos listas, cada lista representa una fila y cada elemento de la lista una clave que representa la columna.
fig, axd = plt.subplot_mosaic([['upper left', 'upper right'],
['lower left', 'lower right']],
figsize=(5.5, 3.5), layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Cuadrículas de relación de aspecto fija Ejes #
Los ejes de relación de aspecto fijo son comunes para imágenes o mapas. Sin embargo, presentan un desafío para el diseño porque se imponen dos conjuntos de restricciones en el tamaño de los ejes: que encajen en la figura y que tengan una relación de aspecto establecida. Esto conduce a grandes brechas entre los ejes de forma predeterminada:
fig, axs = plt.subplots(2, 2, layout="constrained", figsize=(5.5, 3.5))
for ax in axs.flat:
ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes')
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes')
Una forma de abordar esto es cambiar el aspecto de la figura para que esté cerca de la relación de aspecto de los ejes, sin embargo, eso requiere prueba y error. Matplotlib también proporciona layout="compressed"
, que funcionará con cuadrículas simples para reducir las brechas entre los ejes. ( mpl_toolkits
También permite ImageGrid
lograr un efecto similar, pero con una clase de ejes no estándar).
fig, axs = plt.subplots(2, 2, layout="compressed", figsize=(5.5, 3.5))
for ax in axs.flat:
ax.set_aspect(1)
fig.suptitle('Fixed aspect Axes: compressed')
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes: compressed')
Ejes que abarcan filas o columnas en una cuadrícula #
A veces queremos que los ejes abarquen filas o columnas de la cuadrícula. En realidad, hay varias formas de lograr esto, pero la más conveniente es probablemente usar subplot_mosaic
repitiendo una de las teclas:
fig, axd = plt.subplot_mosaic([['upper left', 'right'],
['lower left', 'right']],
figsize=(5.5, 3.5), layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Vea a continuación la descripción de cómo hacer lo mismo usando
GridSpec
o subplot2grid
.
Anchos o alturas variables en una cuadrícula #
Ambos subplots
y subplot_mosaic
permiten que las filas en la cuadrícula tengan diferentes alturas y las columnas tengan diferentes anchos usando el argumento de palabra clave gridspec_kw . Los parámetros de espaciado aceptados por GridSpec
se pueden pasar a subplots
y
subplot_mosaic
:
gs_kw = dict(width_ratios=[1.4, 1], height_ratios=[1, 2])
fig, axd = plt.subplot_mosaic([['upper left', 'right'],
['lower left', 'right']],
gridspec_kw=gs_kw, figsize=(5.5, 3.5),
layout="constrained")
for k in axd:
annotate_axes(axd[k], f'axd["{k}"]', fontsize=14)
fig.suptitle('plt.subplot_mosaic()')
Text(0.5, 0.9880942857142857, 'plt.subplot_mosaic()')
Diseños de ejes anidados #
A veces es útil tener dos o más cuadrículas de ejes que no necesiten estar relacionados entre sí. La forma más sencilla de lograr esto es usar Figure.subfigures
. Tenga en cuenta que los diseños de las subfiguras son independientes, por lo que las columnas de los ejes en cada subfigura no están necesariamente alineadas. Vea a continuación una forma más detallada de lograr el mismo efecto con GridSpecFromSubplotSpec
.
fig = plt.figure(layout="constrained")
subfigs = fig.subfigures(1, 2, wspace=0.07, width_ratios=[1.5, 1.])
axs0 = subfigs[0].subplots(2, 2)
subfigs[0].set_facecolor('0.9')
subfigs[0].suptitle('subfigs[0]\nLeft side')
subfigs[0].supxlabel('xlabel for subfigs[0]')
axs1 = subfigs[1].subplots(3, 1)
subfigs[1].suptitle('subfigs[1]')
subfigs[1].supylabel('ylabel for subfigs[1]')
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')
También es posible anidar ejes usando subplot_mosaic
listas anidadas. Este método no utiliza subfiguras, como el anterior, por lo que carece de la capacidad de agregar por subfigura suptitle
y supxlabel
, etc. Más bien, es un envoltorio de conveniencia en torno al subgridspec
método que se describe a continuación.
Métodos de grilla avanzados y de bajo nivel #
Internamente, la disposición de una cuadrícula de ejes se controla mediante la creación de instancias de GridSpec
y SubplotSpec
. GridSpec define una cuadrícula de celdas (posiblemente no uniforme). La indexación en GridSpec devuelve una SubplotSpec que cubre una o más celdas de cuadrícula y se puede usar para especificar la ubicación de un eje.
Los siguientes ejemplos muestran cómo usar métodos de bajo nivel para organizar ejes usando objetos GridSpec .
Rejilla básica 2x2 #
Podemos lograr una cuadrícula de 2x2 de la misma manera que
:plt.subplots(2, 2)
fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(ncols=2, nrows=2)
ax0 = fig.add_subplot(spec[0, 0])
annotate_axes(ax0, 'ax0')
ax1 = fig.add_subplot(spec[0, 1])
annotate_axes(ax1, 'ax1')
ax2 = fig.add_subplot(spec[1, 0])
annotate_axes(ax2, 'ax2')
ax3 = fig.add_subplot(spec[1, 1])
annotate_axes(ax3, 'ax3')
fig.suptitle('Manually added subplots using add_gridspec')
Text(0.5, 0.9880942857142857, 'Manually added subplots using add_gridspec')
Ejes que abarcan filas o cuadrículas en una cuadrícula #
Podemos indexar la matriz de especificaciones utilizando la sintaxis de segmento NumPy
y los nuevos ejes abarcarán el segmento. Esto sería lo mismo que :fig, axd = plt.subplot_mosaic([['ax0', 'ax0'], ['ax1', 'ax2']], ...)
fig = plt.figure(figsize=(5.5, 3.5), layout="constrained")
spec = fig.add_gridspec(2, 2)
ax0 = fig.add_subplot(spec[0, :])
annotate_axes(ax0, 'ax0')
ax10 = fig.add_subplot(spec[1, 0])
annotate_axes(ax10, 'ax10')
ax11 = fig.add_subplot(spec[1, 1])
annotate_axes(ax11, 'ax11')
fig.suptitle('Manually added subplots, spanning a column')
Text(0.5, 0.9880942857142857, 'Manually added subplots, spanning a column')
Ajustes manuales a un diseño de GridSpec #
Cuando se usa explícitamente GridSpec , puede ajustar los parámetros de diseño de las subparcelas que se crean a partir de GridSpec . Tenga en cuenta que esta opción no es compatible constrained_layout
o
Figure.tight_layout
ignora la izquierda y la derecha y ajusta los tamaños de las subparcelas para llenar la figura. Por lo general, dicha colocación manual requiere iteraciones para que las etiquetas de marcación de los ejes no se superpongan a los ejes.
Estos parámetros de espaciado también se pueden pasar a subplots
y
subplot_mosaic
como argumento gridspec_kw .
fig = plt.figure(layout=None, facecolor='0.9')
gs = fig.add_gridspec(nrows=3, ncols=3, left=0.05, right=0.75,
hspace=0.1, wspace=0.05)
ax0 = fig.add_subplot(gs[:-1, :])
annotate_axes(ax0, 'ax0')
ax1 = fig.add_subplot(gs[-1, :-1])
annotate_axes(ax1, 'ax1')
ax2 = fig.add_subplot(gs[-1, -1])
annotate_axes(ax2, 'ax2')
fig.suptitle('Manual gridspec with right=0.75')
Text(0.5, 0.98, 'Manual gridspec with right=0.75')
Diseños anidados con SubplotSpec #
Puede crear un diseño anidado similar al subfigures
uso
de subgridspec
. Aquí se
alinean las espinas de los ejes .
Tenga en cuenta que esto también está disponible desde el más detallado
gridspec.GridSpecFromSubplotSpec
.
fig = plt.figure(layout="constrained")
gs0 = fig.add_gridspec(1, 2)
gs00 = gs0[0].subgridspec(2, 2)
gs01 = gs0[1].subgridspec(3, 1)
for a in range(2):
for b in range(2):
ax = fig.add_subplot(gs00[a, b])
annotate_axes(ax, f'axLeft[{a}, {b}]', fontsize=10)
if a == 1 and b == 1:
ax.set_xlabel('xlabel')
for a in range(3):
ax = fig.add_subplot(gs01[a])
annotate_axes(ax, f'axRight[{a}, {b}]')
if a == 2:
ax.set_ylabel('ylabel')
fig.suptitle('nested gridspecs')
Text(0.5, 0.99131875, 'nested gridspecs')
Aquí hay un ejemplo más sofisticado de GridSpec anidado : creamos una cuadrícula externa de 4x4 con cada celda que contiene una cuadrícula interna de 3x3 de Axes. Delineamos la cuadrícula exterior de 4x4 ocultando las espinas correspondientes en cada una de las cuadrículas interiores de 3x3.
def squiggle_xy(a, b, c, d, i=np.arange(0.0, 2*np.pi, 0.05)):
return np.sin(i*a)*np.cos(i*b), np.sin(i*c)*np.cos(i*d)
fig = plt.figure(figsize=(8, 8), constrained_layout=False)
outer_grid = fig.add_gridspec(4, 4, wspace=0, hspace=0)
for a in range(4):
for b in range(4):
# gridspec inside gridspec
inner_grid = outer_grid[a, b].subgridspec(3, 3, wspace=0, hspace=0)
axs = inner_grid.subplots() # Create all subplots for the inner grid.
for (c, d), ax in np.ndenumerate(axs):
ax.plot(*squiggle_xy(a + 1, b + 1, c + 1, d + 1))
ax.set(xticks=[], yticks=[])
# show only the outside spines
for ax in fig.get_axes():
ss = ax.get_subplotspec()
ax.spines.top.set_visible(ss.is_first_row())
ax.spines.bottom.set_visible(ss.is_last_row())
ax.spines.left.set_visible(ss.is_first_col())
ax.spines.right.set_visible(ss.is_last_col())
plt.show()
Más lectura #
Más detalles sobre el mosaico de subparcelas .
Más detalles sobre el diseño restringido , utilizado para alinear el espaciado en la mayoría de estos ejemplos.
Referencias
En este ejemplo se muestra el uso de las siguientes funciones, métodos, clases y módulos:
Tiempo total de ejecución del script: ( 0 minutos 13.006 segundos)