Как разместить букву в углу подпункта, включая метки оси (не угол оси) - PullRequest
1 голос
/ 29 апреля 2019

Я хочу пометить вспомогательные участки буквами в верхнем левом углу (A, B, C, ...), которые выровнены либо по меткам, либо по фактическому углу вспомогательного графика (не по оси).

Если вспомогательные участки имеют разную ширину, я больше не могу использовать текст со смещением в координатах преобразования оси, поскольку это приведет к различным расстояниям для каждого вспомогательного участка.Поэтому я обычно использую преобразование смещения.Но это больше не работает, если ylabels имеют разную ширину.В настоящее время я также наблюдаю за смещением для каждого графика, но этого недостаточно.

Это то, что у меня есть:

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

fig = plt.figure(figsize=(5, 2), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1, 2, 3])
axes = [fig.add_subplot(gs[i]) for i in range(3)]

ylabels = ["flat label", "bigger\nlabel", "even\nbigger\nlabel"]
labels = ["A", "B", "C"]

scaledtrans = transforms.ScaledTranslation(-0.4, 0, fig.dpi_scale_trans)

for ax, ylabel, label in zip(axes, ylabels, labels):
    ax.set_ylabel(ylabel)
    ax.text(0, 1, label, fontsize=12, fontweight="bold", va="bottom", ha="left",
           transform=ax.transAxes + scaledtrans)

Как вы можете видеть на рисунке ниже, меткинаходятся на одинаковом расстоянии от осей шипов, но я хочу, чтобы они были выровнены по левому краю илабел или углу вспомогательных участков, который в этом случае совпадал бы по горизонтали с илабелами.TransSubplot пока нет, только transAxes и transFigure

enter image description here

1 Ответ

1 голос
/ 29 апреля 2019

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

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 2), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1, 2, 3])
axes = [fig.add_subplot(gs[i]) for i in range(3)]

ylabels = ["flat label", "bigger\nlabel", "even\nbigger\nlabel"]
labels = ["A", "B", "C"]

for ax, ylabel in zip(axes, ylabels):
    ax.set_ylabel(ylabel)

fig.canvas.draw()

for ax, label in zip(axes, labels):
    bbox = ax.get_tightbbox(fig.canvas.get_renderer())
    fig.text(bbox.x0, bbox.y1, label, fontsize=12, fontweight="bold", va="top", ha="left",
             transform=None)

plt.show()

enter image description here

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

import matplotlib.pyplot as plt

fig = plt.figure(figsize=(5, 2), constrained_layout=True)
gs = fig.add_gridspec(1, 3, width_ratios=[1, 2, 3])
axes = [fig.add_subplot(gs[i]) for i in range(3)]

ylabels = ["flat label", "bigger\nlabel", "even\nbigger\nlabel"]
labels = ["A", "B", "C"]

for ax, ylabel in zip(axes, ylabels):
    ax.set_ylabel(ylabel)

fig.canvas.draw()

axlabels = [fig.text(0,0, label, fontsize=12, fontweight="bold", va="top", ha="left")
            for ax, label in zip(axes, labels)]

def update_labels(evt=None):
    trans = fig.transFigure.inverted()
    for ax, label in zip(axes, axlabels):
        bbox = ax.get_tightbbox(fig.canvas.get_renderer())
        label.set_position(trans.transform_point([bbox.x0, bbox.y1]))

update_labels()
cid = fig.canvas.mpl_connect("draw_event", update_labels)

plt.show()

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

...