Como remover lacunas entre subtramas em matplotlib?

116

O código abaixo produz lacunas entre os subplots. Como faço para remover as lacunas entre os subplots e tornar a imagem uma grade compacta?

insira a descrição da imagem aqui

import matplotlib.pyplot as plt

for i in range(16):
    i = i + 1
    ax1 = plt.subplot(4, 4, i)
    plt.axis('on')
    ax1.set_xticklabels([])
    ax1.set_yticklabels([])
    ax1.set_aspect('equal')
    plt.subplots_adjust(wspace=None, hspace=None)
plt.show()
user3006135
fonte
2
poste um link e ele poderá ser editado em. Nonenão está fazendo o que você pensa, significa 'usar o padrão'.
tacaswell
Tentei adicionar números em vez de 'Nenhum', mas isso não resolveu o problema.
user3006135
4
plt.subplots_adjust(wspace=0, hspace=0)resolveria seu problema, não fosse pelo fato de você usar 'equal'aspecto. Veja minha resposta para detalhes.
apdnu

Respostas:

100

Você pode usar gridspec para controlar o espaçamento entre os eixos. Há mais informações aqui.

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

plt.figure(figsize = (4,4))
gs1 = gridspec.GridSpec(4, 4)
gs1.update(wspace=0.025, hspace=0.05) # set the spacing between axes. 

for i in range(16):
   # i = i + 1 # grid spec indexes from 0
    ax1 = plt.subplot(gs1[i])
    plt.axis('on')
    ax1.set_xticklabels([])
    ax1.set_yticklabels([])
    ax1.set_aspect('equal')

plt.show()

eixos muito próximos

Molly
fonte
35
Não está limitado a GridSpec, se você pegar a figura na criação, você também pode definir as distâncias com:fig.subplots_adjust(hspace=, wspace=)
Rutger Kassies
3
o que significa a última linha do forloop?
Ciprian Tomoiagă
Essa é uma dica muito legal, mas não adianta subplots. Essa resposta realiza o trabalho sem sacrifícios subplots.
wizclown
Existe uma maneira de remover o espaçamento horizontal apenas entre a primeira e a segunda fileiras de eixos?
Stefano
136

O problema é o uso de aspect='equal', que evita que as subtramas se estendam até uma proporção de aspecto arbitrária e preencham todo o espaço vazio.

Normalmente, isso funcionaria:

import matplotlib.pyplot as plt

ax = [plt.subplot(2,2,i+1) for i in range(4)]

for a in ax:
    a.set_xticklabels([])
    a.set_yticklabels([])

plt.subplots_adjust(wspace=0, hspace=0)

O resultado é este:

No entanto, com aspect='equal', como no seguinte código:

import matplotlib.pyplot as plt

ax = [plt.subplot(2,2,i+1) for i in range(4)]

for a in ax:
    a.set_xticklabels([])
    a.set_yticklabels([])
    a.set_aspect('equal')

plt.subplots_adjust(wspace=0, hspace=0)

Isso é o que temos:

A diferença neste segundo caso é que você forçou os eixos xey a terem o mesmo número de unidades / pixel. Uma vez que os eixos vão de 0 a 1 por padrão (ou seja, antes de plotar qualquer coisa), o uso de aspect='equal'força cada eixo a ser um quadrado. Como a figura não é um quadrado, o pyplot adiciona um espaçamento extra entre os eixos horizontalmente.

Para contornar esse problema, você pode definir sua figura para ter a proporção correta. Vamos usar a interface pyplot orientada a objetos aqui, que considero superior em geral:

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(8,8)) # Notice the equal aspect ratio
ax = [fig.add_subplot(2,2,i+1) for i in range(4)]

for a in ax:
    a.set_xticklabels([])
    a.set_yticklabels([])
    a.set_aspect('equal')

fig.subplots_adjust(wspace=0, hspace=0)

Aqui está o resultado:

apdnu
fonte
3
Obrigado! sua resposta é simples e funciona perfeitamente. plt.subplots_adjust(wspace=0, hspace=0)
MohamedEzz
35

Sem recorrer a gridspec inteiramente, o seguinte também pode ser usado para remover as lacunas, definindo wspace e hspace como zero:

import matplotlib.pyplot as plt

plt.clf()
f, axarr = plt.subplots(4, 4, gridspec_kw = {'wspace':0, 'hspace':0})

for i, ax in enumerate(f.axes):
    ax.grid('on', linestyle='--')
    ax.set_xticklabels([])
    ax.set_yticklabels([])

plt.show()
plt.close()

Resultando em:

.

Herpes Free Engineer
fonte
4

Você já tentou plt.tight_layout()?

com plt.tight_layout() insira a descrição da imagem aqui sem ele: insira a descrição da imagem aqui

Ou: algo assim (use add_axes)

left=[0.1,0.3,0.5,0.7]
width=[0.2,0.2, 0.2, 0.2]
rectLS=[]
for x in left:
   for y in left:
       rectLS.append([x, y, 0.2, 0.2])
axLS=[]
fig=plt.figure()
axLS.append(fig.add_axes(rectLS[0]))
for i in [1,2,3]:
     axLS.append(fig.add_axes(rectLS[i],sharey=axLS[-1]))    
axLS.append(fig.add_axes(rectLS[4]))
for i in [1,2,3]:
     axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))
axLS.append(fig.add_axes(rectLS[8]))
for i in [5,6,7]:
     axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))     
axLS.append(fig.add_axes(rectLS[12]))
for i in [9,10,11]:
     axLS.append(fig.add_axes(rectLS[i+4],sharex=axLS[i],sharey=axLS[-1]))

Se você não precisa compartilhar eixos, simplesmente axLS=map(fig.add_axes, rectLS) insira a descrição da imagem aqui

CT Zhu
fonte
Tentei um layout justo, mas não eliminou as lacunas, que é o que eu quero. A solução gridspec funcionou. Obrigado pelas sugestões.
user3006135
Isso funcionou muito bem em conjunto com as outras sugestões. tight_layout () ajudou a remover o espaço em branco acima e nas laterais da trama que não servia para nada.
DChaps
0

Com versões recentes de matplotlib, você pode tentar o Layout restrito . No plt.subplot()entanto, isso não funciona , então você precisa usar em seu plt.subplots()lugar:

fig, axs = plt.subplots(4, 4, constrained_layout=True)
Michel de Ruiter
fonte