Общие меткой х/ylabel для библиотек matplotlib сюжетных линий



у меня есть следующий сюжет:



fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)


а теперь я хотел бы дать этот участок общей оси X и y оси. С помощью "common" я имею в виду, что под всей сеткой подзаголовков должна быть одна большая метка оси x и одна большая метка оси y справа. Я не могу найти ничего об этом в документации plt.subplots, и мои гуглинги предполагают, что мне нужно сделать большой plt.subplot(111) для начала - но как мне тогда поместить мои 5*2 подзаголовки в это с помощью plt.subplots?

572   6  

6 ответов:

Это похоже на то, что вы на самом деле хотите. Он применяет тот же подход ответ к вашему конкретному случаю:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(nrows=3, ncols=3, sharex=True, sharey=True, figsize=(6, 6))

fig.text(0.5, 0.04, 'common X', ha='center')
fig.text(0.04, 0.5, 'common Y', va='center', rotation='vertical')

Multiple plots with common axes label

без sharex=True, sharey=True вы получаете:

enter image description here

С ним вы должны получить его лучше:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))

plt.tight_layout()

enter image description here

но если вы хотите добавить дополнительные метки, Вы должны добавить их только к краевым участкам:

fig, axes2d = plt.subplots(nrows=3, ncols=3,
                           sharex=True, sharey=True,
                           figsize=(6,6))

for i, row in enumerate(axes2d):
    for j, cell in enumerate(row):
        cell.imshow(np.random.rand(32,32))
        if i == len(axes2d) - 1:
            cell.set_xlabel("noise column: {0:d}".format(j + 1))
        if j == 0:
            cell.set_ylabel("noise row: {0:d}".format(i + 1))

plt.tight_layout()

enter image description here

добавление метки для каждого участка испортило бы его (возможно, есть способ автоматически обнаруживать повторяющиеся метки, но я не знаю об этом).

С помощью команды:

fig,ax = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

вы использовали возвращает кортеж, состоящий из фигуры и списка экземпляров осей, это уже достаточно, чтобы сделать что-то вроде (обратите внимание, что я изменил fig,axдо fig,axes):

fig,axes = plt.subplots(5,2,sharex=True,sharey=True,figsize=fig_size)

for ax in axes:
    ax.set_xlabel('Common x-label')
    ax.set_ylabel('Common y-label')

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

также может быть очень полезно включить

fig.tight_layout()

в конец файла, перед plt.show(), для того, чтобы избежать дублирования меток.

я столкнулся с подобной проблемой при построении сетки графиков. Графики состоял из двух частей (верхней и нижней). Y-метка должна была быть сосредоточена на обеих частях.

Я не хотел использовать решение, которое зависит от знания положения на внешней фигуре (например, рис.text ()), поэтому я манипулировал y-позицией функции set_ylabel (). Обычно он равен 0,5, к середине участка он добавляется. Поскольку заполнение между частями (hspace) в моем коде было равно нулю, я мог вычислите середину двух частей относительно верхней части.

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

# Create outer and inner grid
outerGrid = gridspec.GridSpec(2, 3, width_ratios=[1,1,1], height_ratios=[1,1])
somePlot = gridspec.GridSpecFromSubplotSpec(2, 1,
               subplot_spec=outerGrid[3], height_ratios=[1,3], hspace = 0)

# Add two partial plots
partA = plt.subplot(somePlot[0])
partB = plt.subplot(somePlot[1])

# No x-ticks for the upper plot
plt.setp(partA.get_xticklabels(), visible=False)

# The center is (height(top)-height(bottom))/(2*height(top))
# Simplified to 0.5 - height(bottom)/(2*height(top))
mid = 0.5-somePlot.get_height_ratios()[1]/(2.*somePlot.get_height_ratios()[0])
# Place the y-label
partA.set_ylabel('shared label', y = mid)

plt.show()

картинка

минусы:

  • горизонтальное расстояние до участка основано на верхней части, нижние тики могут распространяться на метку.

  • формула не учитывает расстояние между частями.

  • выдает исключение, когда высота верхней части будет 0.

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

я обнаружил более надежный метод:

если вы знаете bottom и top кварги, которые вошли в GridSpec инициализация, или вы иначе знаете положение ребер ваших осей в Figure координаты, вы также можете указать позицию ylabel в Figure координаты с некоторой причудливой магией "преобразования". Например:

import matplotlib.transforms as mtransforms
bottom, top = .1, .9
f, a = plt.subplots(nrows=2, ncols=1, bottom=bottom, top=top)
avepos = (bottom+top)/2
a[0].yaxis.label.set_transform(mtransforms.blended_transform_factory(
       mtransforms.IdentityTransform(), f.transFigure # specify x, y transform
       )) # changed from default blend (IdentityTransform(), a[0].transAxes)
a[0].yaxis.label.set_position((0, avepos))
a[0].set_ylabel('Hello, world!')

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

кроме того, если вы даже не используете set_position, ylabel будет отображаться по умолчанию ровно на полпути вверх по фигуре. Я предполагаю, что это потому, что когда метка наконец-то, matplotlib использует 0,5 для y-координата без проверки того, изменилось ли базовое преобразование координат.

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

fig_size = [8, 6]
fig, ax = plt.subplots(5, 2, sharex=True, sharey=True, figsize=fig_size)
# Reserve space for axis labels
ax[-1, 0].set_xlabel('.', color=(0, 0, 0, 0))
ax[-1, 0].set_ylabel('.', color=(0, 0, 0, 0))
# Make common axis labels
fig.text(0.5, 0.04, 'common X', va='center', ha='center', fontsize=rcParams['axes.labelsize'])
fig.text(0.04, 0.5, 'common Y', va='center', ha='center', rotation='vertical', fontsize=rcParams['axes.labelsize'])

enter image description here enter image description here

Comments

    Ничего не найдено.