Organizando vários eixos em uma figura #

Freqüentemente, mais de um eixo é necessário em uma figura por vez, geralmente organizado em uma grade regular. O Matplotlib possui uma variedade de ferramentas para trabalhar com grades de eixos que evoluíram ao longo da história da biblioteca. Aqui discutiremos as ferramentas que achamos que os usuários devem usar com mais frequência, as ferramentas que sustentam como os Axes são organizados e mencionamos algumas das ferramentas mais antigas.

Observação

Matplotlib usa Axes para se referir à área de desenho que contém dados, eixos x e y, marcações, rótulos, títulos, etc. Consulte Partes de uma figura para obter mais detalhes. Outro termo frequentemente usado é "subplot", que se refere a um Axes que está em uma grade com outros objetos Axes.

Visão geral #

Crie combinações em forma de grade de eixos #

subplots

A função principal usada para criar figuras e uma grade de eixos. Ele cria e coloca todos os eixos na figura de uma vez e retorna uma matriz de objetos com alças para os eixos na grade. Veja Figure.subplots.

ou

subplot_mosaic

Uma maneira simples de criar figuras e uma grade de eixos, com a flexibilidade adicional de que os eixos também podem abranger linhas ou colunas. Os eixos são retornados em um dicionário rotulado em vez de uma matriz. Veja também Figure.subplot_mosaice Composição de figuras complexas e semânticas .

Às vezes é natural ter mais de um grupo distinto de grades de Axes, caso em que o Matplotlib tem o conceito de SubFigure:

SubFigure

Uma figura virtual dentro de uma figura.

Ferramentas subjacentes #

Subjacente a estes estão os conceitos de a GridSpece a SubplotSpec:

GridSpec

Especifica a geometria da grade em que uma subtrama será colocada. O número de linhas e o número de colunas da grade precisam ser definidos. Opcionalmente, os parâmetros de layout da subtrama (por exemplo, esquerda, direita, etc.) podem ser ajustados.

SubplotSpec

Especifica a localização da subtrama no dado GridSpec.

Adicionando eixos únicos por vez #

As funções acima criam todos os eixos em uma única chamada de função. Também é possível adicionar eixos um de cada vez, e era assim que o Matplotlib funcionava originalmente. Fazer isso geralmente é menos elegante e flexível, embora às vezes útil para trabalho interativo ou para colocar um eixo em um local personalizado:

add_axes

Adiciona um único eixo em um local especificado por em frações da largura ou altura da figura.[left, bottom, width, height]

subplotouFigure.add_subplot

Adiciona uma única subtrama em uma figura, com indexação baseada em 1 (herdada do Matlab). Colunas e linhas podem ser estendidas especificando um intervalo de células de grade.

subplot2grid

Semelhante a pyplot.subplot, mas usa indexação baseada em 0 e divisão de python bidimensional para escolher células.

Métodos de alto nível para fazer grades #

Grade básica 2x2 #

Podemos criar uma grade básica de eixos 2 por 2 usando subplots. Ele retorna uma Figure instância e uma matriz de Axesobjetos. Os objetos Axes podem ser usados ​​para acessar métodos para colocar artistas nos Axes; aqui usamos annotate, mas outros exemplos poderiam 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.subplots()
Text(0.5, 0.9880942857142857, 'plt.subplots()')

Anotaremos muitos eixos, então vamos encapsular a anotação, em vez de ter aquele grande pedaço de código de anotação sempre que precisarmos:

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")

O mesmo efeito pode ser obtido com subplot_mosaic, mas o tipo de retorno é um dicionário em vez de um array, onde o usuário pode dar às chaves significados úteis. Aqui fornecemos duas listas, cada lista representando uma linha e cada elemento na lista uma chave representando a coluna.

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()')

Grades de proporção de aspecto fixo Eixos #

Eixos de proporção fixa são comuns para imagens ou mapas. No entanto, eles representam um desafio para o layout porque dois conjuntos de restrições estão sendo impostos ao tamanho dos eixos - que eles caibam na figura e que tenham uma proporção definida. Isso leva a grandes lacunas entre os eixos por padrão:

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')
Eixos de aspecto fixo
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes')

Uma maneira de resolver isso é alterar o aspecto da figura para ficar próximo à proporção dos eixos, mas isso requer tentativa e erro. Matplotlib também fornece layout="compressed", que funcionará com grades simples para reduzir as lacunas entre os eixos. (O mpl_toolkitstambém fornece ImageGridum efeito semelhante, mas com uma classe de machados não padrão).

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')
Eixos de aspecto fixo: compactados
Text(0.5, 0.9880942857142857, 'Fixed aspect Axes: compressed')

Eixos abrangendo linhas ou colunas em uma grade #

Às vezes, queremos que os eixos abranjam linhas ou colunas da grade. Na verdade, existem várias maneiras de fazer isso, mas a mais conveniente é provavelmente subplot_mosaicrepetir uma das 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()')

Veja abaixo a descrição de como fazer a mesma coisa usando GridSpecou subplot2grid.

Larguras ou alturas variáveis ​​em uma grade #

Ambos subplotse subplot_mosaicpermitem que as linhas na grade tenham alturas diferentes e as colunas tenham larguras diferentes usando o argumento de palavra-chave gridspec_kw . Parâmetros de espaçamento aceitos por GridSpec podem ser passados ​​para subplotse 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()')

Layouts de eixos aninhados #

Às vezes é útil ter duas ou mais grades de eixos que podem não precisar estar relacionadas entre si. A maneira mais simples de fazer isso é usar Figure.subfigures. Observe que os layouts das subfiguras são independentes, portanto, as lombadas dos Axes em cada subfigura não estão necessariamente alinhadas. Veja abaixo uma maneira mais detalhada de obter o mesmo efeito com 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]')
arranjando eixos
Text(0.016867713730569944, 0.5, 'ylabel for subfigs[1]')

Também é possível aninhar eixos usando subplot_mosaiclistas aninhadas. Este método não usa subfiguras, como acima, portanto, não tem a capacidade de adicionar por subfigura suptitlee supxlabel, etc. Em vez disso, é um wrapper de conveniência em torno do subgridspec método descrito abaixo.

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}"]')
arranjando eixos

Métodos de grade avançados e de baixo nível #

Internamente, o arranjo de uma grade de Axes é controlado pela criação de instâncias de GridSpece SubplotSpec. GridSpec define uma grade (possivelmente não uniforme) de células. A indexação no GridSpec retorna um SubplotSpec que abrange uma ou mais células da grade e pode ser usado para especificar a localização de um Axes.

Os exemplos a seguir mostram como usar métodos de baixo nível para organizar eixos usando objetos GridSpec .

Grade básica 2x2 #

Podemos realizar uma grade 2x2 da mesma maneira 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')
Subparcelas adicionadas manualmente usando add_gridspec
Text(0.5, 0.9880942857142857, 'Manually added subplots using add_gridspec')

Eixos abrangendo linhas ou grades em uma grade #

Podemos indexar a matriz de especificações usando a sintaxe de fatia NumPy e os novos eixos abrangerão a fatia. Isso seria o mesmo 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')
Subtramas adicionadas manualmente, abrangendo uma coluna
Text(0.5, 0.9880942857142857, 'Manually added subplots, spanning a column')

Ajustes manuais para um layout GridSpec #

Quando um GridSpec é usado explicitamente, você pode ajustar os parâmetros de layout das subtramas que são criadas a partir do GridSpec . Observe que esta opção não é compatível com constrained_layoutou Figure.tight_layoutambas ignoram a esquerda e a direita e ajustam os tamanhos da subtrama para preencher a figura. Normalmente, esse posicionamento manual requer iterações para fazer com que os rótulos de marcação dos eixos não se sobreponham aos eixos.

Esses parâmetros de espaçamento também podem ser passados ​​para subplotse subplot_mosaiccomo o 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 com direita = 0,75
Text(0.5, 0.98, 'Manual gridspec with right=0.75')

Layouts aninhados com SubplotSpec #

Você pode criar um layout aninhado semelhante ao subfiguresuso de subgridspec. Aqui os espinhos dos Axes estão alinhados.

Observe que isso também está disponível no arquivo 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')
especificações de grade aninhadas
Text(0.5, 0.99131875, 'nested gridspecs')

Aqui está um exemplo mais sofisticado de GridSpec aninhado : Criamos uma grade 4x4 externa com cada célula contendo uma grade 3x3 interna de Axes. Delineamos a grade 4x4 externa ocultando os espinhos apropriados em cada uma das grades 3x3 internas.

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()
arranjando eixos

Mais leitura #

Tempo total de execução do script: ( 0 minutos 13.006 segundos)

Galeria gerada por Sphinx-Gallery