2016-12-10 17 views
8

Pracuję nad projektem, w którym muszę ułożyć siatkę z 10 rzędami i 3 kolumnami. Chociaż udało mi się stworzyć fabułę i ułożyć partycje, nie byłem w stanie stworzyć ładnej fabuły bez białej przestrzeni takiej jak ta poniżej z gridspec documentatation. image w/o white space.Jak usunąć spację między subplots w matplotlib.pyplot?

Próbowałem następujące posty, ale nadal nie jest w stanie całkowicie usunąć biały obszar, jak w przykładzie obrazu. Czy ktoś może mi dać jakieś wskazówki? Dzięki!

Oto moje zdjęcie: my image

Poniżej jest mój kod. The full script is here on GitHub. Uwaga: images_2 i images_fool są zarówno numerowanymi tablicami spłaszczonych obrazów o kształcie (1032, 10), natomiast delta jest macierzą obrazu o kształcie (28, 28).

def plot_im(array=None, ind=0): 
    """A function to plot the image given a images matrix, type of the matrix: \ 
    either original or fool, and the order of images in the matrix""" 
    img_reshaped = array[ind, :].reshape((28, 28)) 
    imgplot = plt.imshow(img_reshaped) 

# Output as a grid of 10 rows and 3 cols with first column being original, second being 
# delta and third column being adversaril 
nrow = 10 
ncol = 3 
n = 0 

from matplotlib import gridspec 
fig = plt.figure(figsize=(30, 30)) 
gs = gridspec.GridSpec(nrow, ncol, width_ratios=[1, 1, 1]) 

for row in range(nrow): 
    for col in range(ncol): 
     plt.subplot(gs[n]) 
     if col == 0: 
      #plt.subplot(nrow, ncol, n) 
      plot_im(array=images_2, ind=row) 
     elif col == 1: 
      #plt.subplot(nrow, ncol, n) 
      plt.imshow(w_delta) 
     else: 
      #plt.subplot(nrow, ncol, n) 
      plot_im(array=images_fool, ind=row) 
     n += 1 

plt.tight_layout() 
#plt.show() 
plt.savefig('grid_figure.pdf') 

Odpowiedz

6

notatkę na początku: Jeśli chcesz mieć pełny kontrolować odstępy, unikaj używania plt.tight_layout(), ponieważ będzie próbował rozmieścić wątki na twojej figurze tak, aby były równomiernie i ładnie rozmieszczone. Jest to w większości w porządku i daje przyjemne rezultaty, ale dostosowuje odstępy zgodnie z jego wolą.

Powód, dla którego przykład GridSpec, który cytujesz z galerii przykładów Matplotlib, działa tak dobrze, ponieważ aspekt wątku nie jest wstępnie zdefiniowany. Oznacza to, że podpunkty po prostu rozszerzają się na siatkę i pozostawiają ustawione odstępy (w tym przypadku wspace=0.0, hspace=0.0) niezależnie od rozmiaru figury.

W przeciwieństwie do tego, wykreślasz obrazy z numerem imshow, a aspekt obrazu jest ustawiony domyślnie jako równy (odpowiednik ax.set_aspect("equal")). Powiedział, że możesz oczywiście umieścić set_aspect("auto") na każdym wykresie (i dodatkowo dodać wspace=0.0, hspace=0.0 jako argumenty do GridSpec, jak w przykładzie galerii), które wytworzyłyby wykres bez odstępów.

Jednak przy korzystaniu z obrazów rozsądnie jest zachować taki sam współczynnik proporcji, aby każdy piksel był tak szeroki jak wysoki, a kwadratowa tablica była wyświetlana jako kwadratowy obraz.
Należy wtedy użyć rozmiaru obrazu i marginesów, aby uzyskać oczekiwany wynik. Argument figsize ma postać (szerokość, wysokość) w calach, a tutaj stosunek dwóch liczb może być odtwarzany za pomocą. Parametry podpunktu wspace, hspace, top, bottom, left można ustawić ręcznie, aby uzyskać pożądany wynik. Poniżej przykład:

import numpy as np 
import matplotlib.pyplot as plt 
from matplotlib import gridspec 

nrow = 10 
ncol = 3 

fig = plt.figure(figsize=(4, 10)) 

gs = gridspec.GridSpec(nrow, ncol, width_ratios=[1, 1, 1], 
     wspace=0.0, hspace=0.0, top=0.95, bottom=0.05, left=0.17, right=0.845) 

for i in range(10): 
    for j in range(3): 
     im = np.random.rand(28,28) 
     ax= plt.subplot(gs[i,j]) 
     ax.imshow(im) 
     ax.set_xticklabels([]) 
     ax.set_yticklabels([]) 

#plt.tight_layout() # do not use this!! 
plt.show() 

enter image description here

Edycja:
To nie jest oczywiście pożądane konieczności ręcznego dostrojenia parametrów. Można więc obliczyć kilka optymalnych według liczby rzędów i kolumn.

nrow = 7 
ncol = 7 

fig = plt.figure(figsize=(ncol+1, nrow+1)) 

gs = gridspec.GridSpec(nrow, ncol, 
     wspace=0.0, hspace=0.0, 
     top=1.-0.5/(nrow+1), bottom=0.5/(nrow+1), 
     left=0.5/(ncol+1), right=1-0.5/(ncol+1)) 

for i in range(nrow): 
    for j in range(ncol): 
     im = np.random.rand(28,28) 
     ax= plt.subplot(gs[i,j]) 
     ax.imshow(im) 
     ax.set_xticklabels([]) 
     ax.set_yticklabels([]) 

plt.show() 
+0

Działa jak magia, dzięki @ImportanceOfBeingErnest! Zastanawiasz się, dlaczego używasz figsize = (4, 10) zamiast figsize = (10, 10) ... ten drugi natychmiast przywraca przestrzeń. –

+1

Dlaczego potrzebujesz kwadratu wielkości, jeśli masz 3 razy więcej wierszy niż kolumn? Możesz oczywiście ustawić go na (10,10), a następnie ponownie dostosować parametry "left" i "right". Mój wybór 'figsize = (4, 10)' jest bardziej podyktowany myślą, że posiadanie wierszy 'n' i' m' kolumn, może być odpowiednie dla fig (m + 1, n); reszta jest następnie wykonywana przez dopracowanie parametrów podpozycji. – ImportanceOfBeingErnest

+0

Rozumiem. Tak więc "figsize" tak naprawdę odnosi się do ogólnego rozmiaru obrazu zamiast do wątków. Pomyślałem sobie. –

3

Spróbuj dodać do kodu tej linii:

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

i dla każdego zestawu obiektów oś:

ax.set_xticklabels([]) 
ax.set_yticklabels([]) 
+1

To rozwiązanie będzie działać poprawnie w przypadku wątków z aspektem ustawionym na 'auto'. W przypadku obrazów narysowanych za pomocą 'imshow', jak w przypadku użycia, spowoduje to niepowodzenie. Zobacz moje rozwiązanie. – ImportanceOfBeingErnest

+0

Dziękuję za odpowiedź. To usuwa pionową przestrzeń, ale przestrzeń pozioma wciąż tam jest ... –

Powiązane problemy