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_mosaicy 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 GridSpecy 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]

subplotoFigure.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 Axesobjetos. 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()')
plt.subparcelas()
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()')
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')
Ejes de aspecto fijo
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_toolkitsTambién permite ImageGridlograr 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')
Ejes de aspecto fijo: comprimido
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_mosaicrepitiendo 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()')
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 GridSpeco subplot2grid.

Anchos o alturas variables en una cuadrícula #

Ambos subplotsy subplot_mosaicpermiten 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 subplotsy 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()')
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]')
arreglando hachas
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')

También es posible anidar ejes usando subplot_mosaiclistas anidadas. Este método no utiliza subfiguras, como el anterior, por lo que carece de la capacidad de agregar por subfigura suptitley supxlabel, etc. Más bien, es un envoltorio de conveniencia en torno al subgridspec método que se describe a continuación.

inner = [['innerA'],
         ['innerB']]
outer = [['upper left',  inner],
          ['lower left', 'lower right']]

fig, axd = plt.subplot_mosaic(outer, layout="constrained")
for k in axd:
    annotate_axes(axd[k], f'axd["{k}"]')
arreglando hachas

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 GridSpecy 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')
Subtramas agregadas manualmente usando 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')
Subparcelas agregadas manualmente, que abarcan una columna
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_layouto Figure.tight_layoutignora 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 subplotsy subplot_mosaiccomo 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')
Gridspec manual con 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 subfiguresuso 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')
especificaciones de cuadrícula anidadas
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()
arreglando hachas

Más lectura #

Tiempo total de ejecución del script: ( 0 minutos 13.006 segundos)

Galería generada por Sphinx-Gallery