Улучшите размер / интервал подплотов с помощью большого количества субплотов в matplotlib

313

Очень похоже на этот вопрос, но с той разницей, что моя фигура может быть настолько большой, насколько это необходимо.

Мне нужно создать целую кучу вертикально сложенных графиков в matplotlib. Результат будет сохранен с помощью функции figsave и просмотрен на веб-странице, поэтому мне все равно, каков будет конечный размер изображения, если субплоты расположены так, чтобы они не перекрывались.

Независимо от того, насколько большой я позволю фигуре быть, участки всегда, кажется, пересекаются.

Мой код в настоящее время выглядит как

import matplotlib.pyplot as plt
import my_other_module

titles, x_lists, y_lists = my_other_module.get_data()

fig = plt.figure(figsize=(10,60))
for i, y_list in enumerate(y_lists):
    plt.subplot(len(titles), 1, i)
    plt.xlabel("Some X label")
    plt.ylabel("Some Y label")
    plt.title(titles[i])
    plt.plot(x_lists[i],y_list)
fig.savefig('out.png', dpi=100)
mcstrother
источник

Ответы:

413

Попробуйте использовать plt.tight_layout

В качестве быстрого примера:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(nrows=4, ncols=4)
fig.tight_layout() # Or equivalently,  "plt.tight_layout()"

plt.show()

Без плотной компоновки

введите описание изображения здесь


С плотной компоновкой введите описание изображения здесь

Джо Кингтон
источник
21
Было бы немного яснее, если бы вы показали, что должны выполнить это после кода вашего графика, но прямо перед show ()
pyj
5
tight_layout()ударил и пропустил. Я пытался понять, что отличается, когда это не имеет никакого эффекта (остаются большие поля между сюжетами) - что часто
Джавадба
3
Это сработало очень хорошо для меня, за исключением того, что я наложил заголовок моей фигуры ( suptitle) на заголовок моего участка. В случае, если кто-то сталкивается с подобной проблемой, вот что помогло в моем случае stackoverflow.com/a/45161551/11740420 . А именно, rectпараметрtight_layout()
Сияна Павлова
285

Вы можете использовать, plt.subplots_adjustчтобы изменить интервал между участками (источник)

подпись звонка:

subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)

Значения параметров (и предлагаемые значения по умолчанию):

left  = 0.125  # the left side of the subplots of the figure
right = 0.9    # the right side of the subplots of the figure
bottom = 0.1   # the bottom of the subplots of the figure
top = 0.9      # the top of the subplots of the figure
wspace = 0.2   # the amount of width reserved for blank space between subplots
hspace = 0.2   # the amount of height reserved for white space between subplots

Фактические значения по умолчанию контролируются файлом rc

CyanRook
источник
3
Я пробовал возиться с hspace, но при его увеличении кажется, что все графики уменьшаются без решения проблемы перекрытия. Я также попытался поиграть с другими параметрами, но я не знаю, что на самом деле указывает левый, правый, нижний и верхний.
mcstrother
52
@mcstrother вы можете в интерактивном режиме изменить все 6 из этих параметров, если вы нажмете кнопку «корректировки» после показа графика, а затем скопируете их в код, как только найдете то, что работает.
Ник Т
1
Я не вижу кнопку регулировки. Хотя я в тетради Jupyter. Я попробовал встроенный% matplotlib и блокнот% matplotlib.
Мэтт Кляйнсмит
1
@MattKleinsmith: кнопка настройки имеет всплывающий текст «Настроить подзаголовки» и появляется при обычном использовании Matplotlib без использования ноутбука. Это кнопка слева от кнопки сохранения «дискеты» здесь: pythonspot-9329.kxcdn.com/wp-content/uploads/2016/07/… - обратите внимание, что кнопка выглядит по-разному в зависимости от того, какую оконную систему вы используете используя, но это всегда слева от кнопки сохранения.
Джон Цвинк
@JohnZwinck, ссылка в вашем комментарии сейчас не работает.
user4015990
56

Я обнаружил, что subplots_adjust (hspace = 0.001) - это то, что мне помогло. Когда я использую пробел = Нет, между каждым графиком все еще остается пробел. Установка этого значения очень близко к нулю, однако, кажется, заставляет их выстраиваться. То, что я загрузил здесь, не самый элегантный кусок кода, но вы можете увидеть, как работает hspace.

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as tic

fig = plt.figure()

x = np.arange(100)
y = 3.*np.sin(x*2.*np.pi/100.)

for i in range(5):
    temp = 510 + i
    ax = plt.subplot(temp)
    plt.plot(x,y)
    plt.subplots_adjust(hspace = .001)
    temp = tic.MaxNLocator(3)
    ax.yaxis.set_major_locator(temp)
    ax.set_xticklabels(())
    ax.title.set_visible(False)

plt.show()

введите описание изображения здесь

Алекса Хэлфорд
источник
31
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(10,60))
plt.subplots_adjust( ... )

Метод plt.subplots_adjust :

def subplots_adjust(*args, **kwargs):
    """
    call signature::

      subplots_adjust(left=None, bottom=None, right=None, top=None,
                      wspace=None, hspace=None)

    Tune the subplot layout via the
    :class:`matplotlib.figure.SubplotParams` mechanism.  The parameter
    meanings (and suggested defaults) are::

      left  = 0.125  # the left side of the subplots of the figure
      right = 0.9    # the right side of the subplots of the figure
      bottom = 0.1   # the bottom of the subplots of the figure
      top = 0.9      # the top of the subplots of the figure
      wspace = 0.2   # the amount of width reserved for blank space between subplots
      hspace = 0.2   # the amount of height reserved for white space between subplots

    The actual defaults are controlled by the rc file
    """
    fig = gcf()
    fig.subplots_adjust(*args, **kwargs)
    draw_if_interactive()

или

fig = plt.figure(figsize=(10,60))
fig.subplots_adjust( ... )

Размер картины имеет значение.

«Я пробовал возиться с hspace, но при его увеличении кажется, что все графики уменьшаются без решения проблемы перекрытия».

Таким образом, чтобы создать больше пустого пространства и сохранить размер вспомогательного участка, общее изображение должно быть больше.

Демз
источник
2
Размер изображения имеет значение, больший размер изображения может решить эту проблему! набор plt.figure(figsize=(10, 7)), размер изображения будет 2000 x 1400пикс
Belter
20

Похожий на tight_layoutmatplotlib сейчас (начиная с версии 2.2) constrained_layout. В отличие от того tight_layout, что может быть вызвано в любое время в коде для одного оптимизированного макета,constrained_layout вызвано в это свойство, которое может быть активным и будет оптимизировать макет перед каждым шагом рисования.

Следовательно, его необходимо активировать до или во время создания подзаговора, например, figure(constrained_layout=True)илиsubplots(constrained_layout=True) .

Пример:

import matplotlib.pyplot as plt

fig, axes = plt.subplots(4,4, constrained_layout=True)

plt.show()

введите описание изображения здесь

constrained_layout также может быть установлен через rcParams

plt.rcParams['figure.constrained_layout.use'] = True

Ознакомьтесь с новой записью и руководством по ограниченному макету.

ImportanceOfBeingErnest
источник
1
собираюсь попробовать это: не видел этого варианта - и tight_layoutненадежен
javadba
это звучало многообещающе, но не давало достаточно места (метки осей и заголовки все еще накладывались), и рендеринг занял гораздо больше времени. tight_layout()работал лучше
Craq
2
@craq Правильно, как правило contrained_layout, медленнее, потому что, как видно из этого ответа, он оптимизирует макет перед каждым шагом рисования .
Важное значение
для меня это был самый полезный ответ - для меня тугое_положение всегда улучшает интервал по вертикали, чтобы оставить место для заголовка панели, но за счет обрезания метки оси y каждый раз. Это, напротив, работает отлично, спасибо.
Адриан Томпкинс