Nota
Haga clic aquí para descargar el código de ejemplo completo
Composición figurativa compleja y semántica #
Advertencia
Este tutorial documenta la API experimental/provisional. Estamos lanzando esto en v3.3 para obtener comentarios de los usuarios. Podemos realizar cambios importantes en futuras versiones sin previo aviso.
Colocar ejes en una figura en una cuadrícula no uniforme puede ser tedioso y detallado. Para cuadrículas densas y uniformes, Figure.subplots
pero para diseños más complejos, como ejes que abarcan varias columnas/filas del diseño o dejan algunas áreas de la figura en blanco, puede usar
gridspec.GridSpec
(consulte Organización de varios ejes en una figura ) o colocar manualmente su hachas Figure.subplot_mosaic
tiene como objetivo proporcionar una interfaz para diseñar visualmente sus ejes (como arte ASCII o listas anidadas) para agilizar este proceso.
Esta interfaz, naturalmente, admite nombrar sus ejes.
Figure.subplot_mosaic
devuelve un diccionario tecleado en las etiquetas utilizadas para diseñar la Figura. Al devolver estructuras de datos con nombres, es más fácil escribir código de trazado que sea independiente del diseño de la figura.
Esto está inspirado en un MEP propuesto y la biblioteca de mosaicos para R. Si bien no implementamos el estilo de sobrecarga del operador, proporcionamos una API Pythonic para especificar diseños de ejes (anidados).
import matplotlib.pyplot as plt
import numpy as np
# Helper function used for visualization in the following examples
def identify_axes(ax_dict, fontsize=48):
"""
Helper to identify the Axes in the examples below.
Draws the label in a large font in the center of the Axes.
Parameters
----------
ax_dict : dict[str, Axes]
Mapping between the title / label and the Axes.
fontsize : int, optional
How big the label should be.
"""
kw = dict(ha="center", va="center", fontsize=fontsize, color="darkgrey")
for k, ax in ax_dict.items():
ax.text(0.5, 0.5, k, transform=ax.transAxes, **kw)
Si queremos una cuadrícula de 2x2, podemos usarla, Figure.subplots
que devuelve una matriz 2D en axes.Axes
la que podemos indexar para hacer nuestro trazado.
np.random.seed(19680801)
hist_data = np.random.randn(1_500)
fig = plt.figure(constrained_layout=True)
ax_array = fig.subplots(2, 2, squeeze=False)
ax_array[0, 0].bar(["a", "b", "c"], [5, 7, 9])
ax_array[0, 1].plot([1, 2, 3])
ax_array[1, 0].hist(hist_data, bins="auto")
ax_array[1, 1].imshow([[1, 2], [2, 1]])
identify_axes(
{(j, k): a for j, r in enumerate(ax_array) for k, a in enumerate(r)},
)
Usando Figure.subplot_mosaic
podemos producir el mismo mosaico pero dando a los ejes nombres semánticos
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(
[
["bar", "plot"],
["hist", "image"],
],
)
ax_dict["bar"].bar(["a", "b", "c"], [5, 7, 9])
ax_dict["plot"].plot([1, 2, 3])
ax_dict["hist"].hist(hist_data)
ax_dict["image"].imshow([[1, 2], [2, 1]])
identify_axes(ax_dict)
Una diferencia clave entre Figure.subplots
y
Figure.subplot_mosaic
es el valor devuelto. Mientras que el primero devuelve una matriz para el acceso al índice, el segundo devuelve un diccionario que asigna las etiquetas a las axes.Axes
instancias creadas .
print(ax_dict)
{'bar': <AxesSubplot: label='bar'>, 'plot': <AxesSubplot: label='plot'>, 'hist': <AxesSubplot: label='hist'>, 'image': <AxesSubplot: label='image'>}
Cadena abreviada #
Al restringir las etiquetas de nuestros ejes a caracteres individuales, podemos "dibujar" los ejes que queremos como "arte ASCII". El seguimiento
mosaic = """
AB
CD
"""
nos dará 4 ejes dispuestos en una cuadrícula de 2x2 y generará el mismo mosaico de figuras que el anterior (pero ahora etiquetado con en lugar de ).{"A", "B", "C",
"D"}
{"bar", "plot", "hist", "image"}
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)
Alternativamente, puede usar la notación de cadena más compacta
mosaic = "AB;CD"
le dará la misma composición, donde ";"
se usa como separador de fila en lugar de nueva línea.
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)
Ejes que abarcan múltiples filas/columnas #
Algo que podemos hacer con lo Figure.subplot_mosaic
que usted no puede hacer Figure.subplots
es especificar que los ejes deben abarcar varias filas o columnas.
Si queremos reorganizar nuestros cuatro ejes para que tengan "C"
un tramo horizontal en la parte inferior y "D"
un tramo vertical a la derecha, haríamos
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
ABD
CCD
"""
)
identify_axes(axd)
Si no queremos llenar todos los espacios en la figura con ejes, podemos especificar algunos espacios en la cuadrícula para que estén en blanco
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
A.C
BBB
.D.
"""
)
identify_axes(axd)
Si preferimos usar otro carácter (en lugar de un punto "."
) para marcar el espacio vacío, podemos usar empty_sentinel para especificar el carácter a usar.
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
aX
Xb
""",
empty_sentinel="X",
)
identify_axes(axd)
Internamente no hay ningún significado adjunto a las letras que usamos, ¡cualquier punto de código Unicode es válido!
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""αб
ℝ☢"""
)
identify_axes(axd)
No se recomienda usar espacios en blanco como una etiqueta o un centinela vacío con la abreviatura de cadena porque puede eliminarse mientras se procesa la entrada.
Controlando la creación de mosaicos y subparcelas #
Esta función se basa en gridspec
y puede pasar los argumentos de palabras clave al subyacente gridspec.GridSpec
(igual que Figure.subplots
).
En este caso, queremos usar la entrada para especificar la disposición, pero establecer los anchos relativos de las filas/columnas a través de gridspec_kw .
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
.a.
bAc
.d.
""",
# set the height ratios between the rows
height_ratios=[1, 3.5, 1],
# set the width ratios between the columns
width_ratios=[1, 3.5, 1],
)
identify_axes(axd)
O use los argumentos de palabra clave { izquierda , derecha , abajo , arriba } para posicionar el mosaico general para colocar múltiples versiones del mismo mosaico en una figura
mosaic = """AA
BC"""
fig = plt.figure()
axd = fig.subplot_mosaic(
mosaic,
gridspec_kw={
"bottom": 0.25,
"top": 0.95,
"left": 0.1,
"right": 0.5,
"wspace": 0.5,
"hspace": 0.5,
},
)
identify_axes(axd)
axd = fig.subplot_mosaic(
mosaic,
gridspec_kw={
"bottom": 0.05,
"top": 0.75,
"left": 0.6,
"right": 0.95,
"wspace": 0.5,
"hspace": 0.5,
},
)
identify_axes(axd)
Alternativamente, puede utilizar la función de subfigura:
mosaic = """AA
BC"""
fig = plt.figure(constrained_layout=True)
left, right = fig.subfigures(nrows=1, ncols=2)
axd = left.subplot_mosaic(mosaic)
identify_axes(axd)
axd = right.subplot_mosaic(mosaic)
identify_axes(axd)
También podemos pasar los argumentos utilizados para crear las subparcelas (nuevamente, lo mismo que Figure.subplots
).
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"AB", subplot_kw={"projection": "polar"}
)
identify_axes(axd)
Entrada de lista anidada #
Todo lo que podemos hacer con la taquigrafía de cadena también lo podemos hacer al pasar una lista (internamente convertimos la taquigrafía de cadena en una lista anidada), por ejemplo, usando intervalos, espacios en blanco y gridspec_kw :
axd = plt.figure(constrained_layout=True).subplot_mosaic(
[
["main", "zoom"],
["main", "BLANK"],
],
empty_sentinel="BLANK",
width_ratios=[2, 1],
)
identify_axes(axd)
Además, usando la entrada de lista podemos especificar mosaicos anidados. Cualquier elemento de la lista interna puede ser otro conjunto de listas anidadas:
inner = [
["inner A"],
["inner B"],
]
outer_nested_mosaic = [
["main", inner],
["bottom", "bottom"],
]
axd = plt.figure(constrained_layout=True).subplot_mosaic(
outer_nested_mosaic, empty_sentinel=None
)
identify_axes(axd, fontsize=36)
También podemos pasar una matriz 2D NumPy para hacer cosas como
Tiempo total de ejecución del script: (0 minutos 9.170 segundos)