Jak usunąć luki między wątkami podrzędnymi w matplotlib?

116

Poniższy kod tworzy przerwy między wykresami pobocznymi. Jak usunąć przerwy między wykresami cząstkowymi i sprawić, by obraz był ciasną siatką?

wprowadź opis obrazu tutaj

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
źródło
2
opublikuj link i można go edytować w programie. Nonenie robi tego, co myślisz, oznacza to „użyj domyślnego”.
tacaswell
Próbowałem dodać liczby zamiast „Brak”, ale to nie rozwiązało problemu.
user3006135
4
plt.subplots_adjust(wspace=0, hspace=0)rozwiązałoby twój problem, gdyby nie fakt, że używasz 'equal'aspektu. Zobacz moją odpowiedź po szczegóły.
apdnu

Odpowiedzi:

100

Możesz użyć gridspec do kontrolowania odstępów między osiami. Więcej informacji znajdziesz tutaj.

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

osie bardzo blisko siebie

Pedał
źródło
35
Nie ogranicza się to do tego GridSpec, że jeśli złapiesz figurę podczas tworzenia, możesz również ustawić odległości za pomocą:fig.subplots_adjust(hspace=, wspace=)
Rutger Kassies
3
co oznacza ostatnia linia w forpętli?
Ciprian Tomoiagă
To bardzo fajna wskazówka, ale z niej nie korzysta subplots. Ta odpowiedź pozwala wykonać zadanie bez poświęcania subplots.
wizclown
Czy istnieje sposób na usunięcie odstępów poziomych tylko między pierwszym a drugim rzędem osi?
Stefano
136

Problem polega na używaniu aspect='equal' , które zapobiega rozciągnięciu podpunktów do dowolnego współczynnika kształtu i wypełnieniu całej pustej przestrzeni.

Zwykle to zadziała:

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)

Wynik jest taki:

Jednak z aspect='equal', jak w poniższym kodzie:

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)

Oto, co otrzymujemy:

Różnica w tym drugim przypadku polega na tym, że wymusiłeś na osiach X i Y taką samą liczbę jednostek / piksel. Ponieważ osie domyślnie przechodzą od 0 do 1 (tj. Zanim cokolwiek wykreślisz), użycie aspect='equal'wymusza, aby każda oś była kwadratem. Ponieważ figura nie jest kwadratem, pyplot dodaje dodatkowe odstępy między osiami w poziomie.

Aby obejść ten problem, możesz ustawić figurę tak, aby miała prawidłowe proporcje. Użyjemy tutaj zorientowanego obiektowo interfejsu pyplot, który ogólnie uważam za lepszy:

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)

Oto wynik:

apdnu
źródło
3
Dzięki! Twoja odpowiedź jest prosta i działa doskonale. plt.subplots_adjust(wspace=0, hspace=0)
MohamedEzz
35

Bez całkowitego uciekania się do gridspec , do usunięcia przerw można również użyć następującego polecenia, ustawiając wspace i hspace na 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()

Wynik:

.

Inżynier Herpes Free
źródło
4

Czy próbowałeś plt.tight_layout()?

ze plt.tight_layout() wprowadź opis obrazu tutaj bez niego: wprowadź opis obrazu tutaj

Lub: coś takiego (użyj 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]))

Jeśli nie musisz udostępniać osi, po prostu axLS=map(fig.add_axes, rectLS) wprowadź opis obrazu tutaj

CT Zhu
źródło
Próbowałem ciasnego układu, ale nie pozbyłem się luk, a tego właśnie chcę. Rozwiązanie gridspec zadziałało. Dziękujemy za sugestie.
user3006135
To działało świetnie w połączeniu z innymi sugestiami. tight_layout () pomogło usunąć białą przestrzeń nad i po bokach działki, która nie służyła żadnemu celowi.
DC Być może
0

W przypadku ostatnich wersji matplotlib możesz chcieć wypróbować układ ograniczony . To jednak nie działa plt.subplot(), więc musisz użyćplt.subplots() zamiast tego :

fig, axs = plt.subplots(4, 4, constrained_layout=True)
Michel de Ruiter
źródło