Observação
Clique aqui para baixar o código de exemplo completo
Composição de figuras complexas e semânticas #
Aviso
Este tutorial documenta a API experimental/provisória. Estamos lançando isso na v3.3 para obter feedback do usuário. Podemos fazer alterações importantes em versões futuras sem aviso prévio.
Colocar os eixos em uma figura em uma grade não uniforme pode ser tedioso e prolixo. Para grades densas e uniformes, temos, Figure.subplots
mas para layouts mais complexos, como eixos que abrangem várias colunas/linhas do layout ou deixam algumas áreas da figura em branco, você pode usar
gridspec.GridSpec
(consulte Organizar vários eixos em uma figura ) ou colocar manualmente machados. Figure.subplot_mosaic
visa fornecer uma interface para definir visualmente seus eixos (como arte ASCII ou listas aninhadas) para simplificar esse processo.
Essa interface suporta naturalmente a nomeação de seus eixos.
Figure.subplot_mosaic
retorna um dicionário digitado nos rótulos usados para dispor a Figura. Ao retornar estruturas de dados com nomes, é mais fácil escrever código de plotagem independente do layout da figura.
Isso é inspirado por um MEP proposto e pela biblioteca patchwork para R. Embora não implementemos o estilo de sobrecarga do operador, fornecemos uma API Pythonic para especificar layouts de eixos (aninhados).
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)
Se quisermos uma grade 2x2, podemos usar o Figure.subplots
que retorna uma matriz 2D na axes.Axes
qual podemos indexar para fazer nossa plotagem.
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 produzir o mesmo mosaico, mas dar nomes semânticos aos eixos
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)
Uma diferença fundamental entre Figure.subplots
e
Figure.subplot_mosaic
é o valor de retorno. Enquanto o primeiro retorna um array para acesso ao índice, o segundo retorna um dicionário mapeando os rótulos para as axes.Axes
instâncias criadas
print(ax_dict)
{'bar': <AxesSubplot: label='bar'>, 'plot': <AxesSubplot: label='plot'>, 'hist': <AxesSubplot: label='hist'>, 'image': <AxesSubplot: label='image'>}
String abreviada #
Ao restringir nossos rótulos de eixos a caracteres únicos, podemos "desenhar" os eixos que queremos como "arte ASCII". A seguir
mosaic = """
AB
CD
"""
nos dará 4 eixos dispostos em uma grade 2x2 e gerará o mesmo mosaico de figuras acima (mas agora rotulado com em vez 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)
Como alternativa, você pode usar a notação de string mais compacta
mosaic = "AB;CD"
fornecerá a mesma composição, onde o ";"
é usado como separador de linha em vez de nova linha.
fig = plt.figure(constrained_layout=True)
ax_dict = fig.subplot_mosaic(mosaic)
identify_axes(ax_dict)
Eixos abrangendo várias linhas/colunas #
Algo que podemos fazer com Figure.subplot_mosaic
o que você não pode fazer Figure.subplots
é especificar que um Axes deve abranger várias linhas ou colunas.
Se quisermos reorganizar nossos quatro eixos para que tenham "C"
uma extensão horizontal na parte inferior e "D"
uma extensão vertical à direita, faríamos
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
ABD
CCD
"""
)
identify_axes(axd)
Se não quisermos preencher todos os espaços da Figura com Eixos, podemos especificar alguns espaços na grade para ficarem em branco
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
A.C
BBB
.D.
"""
)
identify_axes(axd)
Se preferirmos usar outro caractere (em vez de um ponto "."
) para marcar o espaço vazio, podemos usar empty_sentinel para especificar o caractere a ser usado.
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""
aX
Xb
""",
empty_sentinel="X",
)
identify_axes(axd)
Internamente, não há significado associado às letras que usamos, qualquer ponto de código Unicode é válido!
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"""αб
ℝ☢"""
)
identify_axes(axd)
Não é recomendado usar espaço em branco como um rótulo ou uma sentinela vazia com a abreviação da string porque ela pode ser removida durante o processamento da entrada.
Controlando a criação de mosaicos e subtramas #
Esse recurso é construído sobre gridspec
e você pode passar os argumentos de palavra-chave para o subjacente gridspec.GridSpec
(o mesmo que Figure.subplots
).
Neste caso, queremos usar a entrada para especificar o arranjo, mas definir as larguras relativas das linhas/colunas via 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)
Ou use os argumentos de palavra-chave { esquerda , direita , inferior , superior } para posicionar o mosaico geral para colocar várias versões do mesmo mosaico em uma 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)
Como alternativa, você pode usar a funcionalidade 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)
Também podemos passar por argumentos usados para criar as subtramas (novamente, o mesmo que Figure.subplots
).
axd = plt.figure(constrained_layout=True).subplot_mosaic(
"AB", subplot_kw={"projection": "polar"}
)
identify_axes(axd)
Entrada de lista aninhada #
Tudo o que podemos fazer com a string abreviada também podemos fazer ao passar em uma lista (internamente convertemos a string abreviada em uma lista aninhada), por exemplo, usando spans, blanks e gridspec_kw :
axd = plt.figure(constrained_layout=True).subplot_mosaic(
[
["main", "zoom"],
["main", "BLANK"],
],
empty_sentinel="BLANK",
width_ratios=[2, 1],
)
identify_axes(axd)
Além disso, usando a entrada de lista, podemos especificar mosaicos aninhados. Qualquer elemento da lista interna pode ser outro conjunto de listas aninhadas:
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)
Também podemos passar um array NumPy 2D para fazer coisas como
Tempo total de execução do script: ( 0 minutos 9,170 segundos)