2016-12-10 3 views
8

Я работаю над проектом, в котором мне нужно собрать сетку из 10 строк и 3 столбца. Хотя я смог сделать сюжеты и упорядочить подзаголовки, я не смог создать хороший сюжет без пробела, такой как этот ниже от gridspec documentatation. image w/o white space.Как удалить пространство между подзаголовками в matplotlib.pyplot?

Я пробовал следующие сообщения, но все еще не смог полностью удалить пустое пространство, как в примере изображения. Может кто-нибудь, пожалуйста, дайте мне несколько советов? Благодаря!

Вот мое изображение: my image

Ниже мой код. The full script is here on GitHub. Примечание: images_2 и images_fool - это как numpy массивы сплюснутых изображений с формой (1032, 10), а delta - массив изображений формы (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') 

ответ

6

примечания в начале: Если вы хотите иметь полный контролируйте расстояние, избегайте использования plt.tight_layout(), так как оно будет пытаться упорядочить графики на вашей фигуре, чтобы они были одинаково и хорошо распределены. Это в основном прекрасно и дает приятные результаты, но регулирует интервал по своему усмотрению.

Причина, по которой пример GridSpec, который вы цитируете в галерее примеров Matplotlib, работает так хорошо, потому что аспект подзаголовков не предопределен. То есть подсети будут просто расширяться на сетке и оставлять заданный интервал (в данном случае wspace=0.0, hspace=0.0) независимо от размера фигуры.

В отличие от этого вы рисуете изображения с imshow, и по умолчанию его размер равен по умолчанию (эквивалент ax.set_aspect("equal")). Тем не менее, вы могли бы, конечно, поставить set_aspect("auto") на каждый сюжет (и дополнительно добавить wspace=0.0, hspace=0.0 в качестве аргументов в GridSpec, как в примере с галереей), что приведет к созданию графика без пробелов.

Однако при использовании изображений имеет смысл поддерживать одинаковое соотношение сторон, чтобы каждый пиксель был как можно большим, а квадратный массив показан как квадратное изображение.
Для этого вам нужно будет сыграть с размером изображения и полями рисунков, чтобы получить ожидаемый результат. Аргумент figsize для фигуры - это цифра (ширина, высота) в дюймах, и здесь можно сыграть соотношение двух чисел. А параметры подзадачи wspace, hspace, top, bottom, left можно отрегулировать вручную, чтобы дать желаемый результат. Ниже приведен пример:

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

Edit:
Это, конечно, желательны, не имея настроить параметры вручную. Таким образом, можно подсчитать некоторые оптимальные по количеству строк и столбцов.

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

Работает как волшебство, спасибо @ImportanceOfBeingErnest! Просто интересно, почему вы используете figsize = (4, 10) вместо figsize = (10, 10) ... последний возвращает пространство сразу. –

+1

Зачем вам нужен квадратный размер фигуры, если у вас в 3 раза больше строк, чем столбцов? Вы можете, конечно, установить его на (10,10), а затем снова изменить параметры «left» и «right». Мой выбор 'figsize = (4, 10)' больше продиктован идеей о том, что наличие столбцов 'n' и' m', может иметь значение figsize (m + 1, n); остальное затем выполняется путем настройки параметров подзадачи. – ImportanceOfBeingErnest

+0

Я вижу. Так что «figsize» действительно относится к общему размеру изображения, а не к подзаголовкам. Я смутился. –

3

Попробуйте добавить в код строки:

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

И для каждого наборе объекта оси:

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

Это решение прекрасно работает в случае подзаголовков с аспектным настройкой на 'auto'. Для изображений, построенных с помощью 'imshow', как в случае использования здесь, он будет терпеть неудачу. См. Мое решение. – ImportanceOfBeingErnest

+0

Спасибо за ваш ответ. Это удаляет вертикальное пространство, но горизонтальное пространство все еще там ... –

Смежные вопросы