Повернуть преобразование на оси Matplotlib в подплот - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь создать фигуру с четырьмя панелями, где нижняя левая панель содержит диаграмму рассеяния, а остальные три панели содержат гистограммы. В верхнем левом углу будет стандартная гистограмма по x-размеру рассеяния, в нижнем правом углу будет повернутая на 90 ° гистограмма для y-измерения. И то, и другое легко сделать в matplotlib.

У меня проблемы с третьей гистограммой, которая должна быть повернутой на 45 ° в правом верхнем углу рисунка, показывающей распределение различий между точками x и y. Я делал такие фигуры раньше, вручную поворачивая и масштабируя оси в Illustrator, но похоже, что matplotlib должен быть в состоянии создавать фигуры, которые уже вращаются с использованием методов преобразования на осях подзаговоров.

Я подумал, что может сработать что-то вроде следующего:

import matplotlib.pyplot as plt
from matplotlib.transforms import Affine2D

fig, ax = plt.subplots(nrows=2, ncols=2, squeeze=True, sharex=False, 
                       sharey=False, figsize=(8,8))
ax[0,1].text(0.5,0.5,'I should be rotated',ha='center',va='center')
t = ax[0,1].get_transform()
ax[0,1].set_transform(t.transform(Affine2D().rotate_deg(45)))

plt.show()

Здесь я пытаюсь получить преобразование от оси, изменить его, а затем заменить его обратно в объект оси. Этот код не имеет никакого эффекта, однако. Любая помощь будет принята с благодарностью.

Отредактировано на основе предложения от ImportanceOfBeingErnest в комментариях:

Я посмотрел демо-версию «Плавающие оси» и теперь получил следующее:

from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
import matplotlib.pyplot as plt

def setup_axes(fig, rect, rotation, axisScale):
    tr = Affine2D().scale(axisScale[0], axisScale[1]).rotate_deg(rotation)

    grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=(-0.5, 3.5, 0, 4))

    ax = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper)
    fig.add_subplot(ax)
    aux_ax = ax.get_aux_axes(tr)

    return ax, aux_ax

fig  = plt.figure(1, figsize=(8, 8))
axes = []
axisOrientation = [0, 0, 270, -45]
axisScale = [[1,1],[2,1],[2,1],[2,1]]
axisPosition = [223,221,224,222]

for i in range(0, len(axisOrientation)):
    ax, aux_ax = setup_axes(fig, axisPosition[i], axisOrientation[i], axisScale[i])
    axes.append(aux_ax)
fig.subplots_adjust(wspace=-0.2, hspace=-0.2, left=0.00, right=0.99, top=0.99, bottom=0.0)
plt.show()

Это приближает меня к тому, чего я хочу:

Demonstration of plot

Я сделаю попытку добавления графика рассеяния и гистограмм к этим осям.

1 Ответ

0 голосов
/ 06 сентября 2018

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

from matplotlib.transforms import Affine2D
import mpl_toolkits.axisartist.floating_axes as floating_axes
import matplotlib.pyplot as plt

def setup_axes(fig, rect, rotation, axisScale, axisLimits, doShift):
    tr_rot = Affine2D().scale(axisScale[0], axisScale[1]).rotate_deg(rotation)

    # This seems to do nothing
    if doShift:
        tr_trn = Affine2D().translate(-90,-5)
    else:
        tr_trn = Affine2D().translate(0,0)

    tr = tr_rot + tr_trn

    grid_helper = floating_axes.GridHelperCurveLinear(tr, extremes=axisLimits)

    ax = floating_axes.FloatingSubplot(fig, rect, grid_helper=grid_helper)
    fig.add_subplot(ax)
    aux_ax = ax.get_aux_axes(tr)

    return ax, aux_ax

fig  = plt.figure(1, figsize=(8, 8))
axes = []
axisOrientation = [0, 0, 270, -45]
axisScale = [[1,1],[6,1],[6,1],[6,1]]
axisPosition = [223,221,224,222]
axisLimits = [(-0.5, 4.5, -0.5, 4.5),
              (-0.5, 4.5, 0, 12),
              (-0.5, 4.5, 0, 12),
              (-3.5, 3.5, 0, 12)]
doShift = [False, False, False, True]

label_axes = []
for i in range(0, len(axisOrientation)):
    ax, aux_ax = setup_axes(fig, axisPosition[i], axisOrientation[i], 
                            axisScale[i], axisLimits[i], doShift[i])
    axes.append(aux_ax)
    label_axes.append(ax)

numPoints = 100
x = []
y = []
for i in range(0,numPoints):
    x.append(np.random.rand() + i/100.0)
    y.append(np.random.rand() + i/100.0 + np.mod(i,2)*2)

axes[0].plot(x,y,ls='none',marker='x')
label_axes[0].axis["bottom"].label.set_text('Variable 1')
label_axes[0].axis["left"].label.set_text('Variable 2')

b = np.linspace(-0.5,4.5,50)
axes[1].hist(x, bins = b)
axes[2].hist(y, bins = b)
b = np.linspace(-3.5,3.5,50)
axes[3].hist(np.array(x)-np.array(y), bins=b)

for i in range(1,len(label_axes)):
    for axisLoc in ['top','left','right']:
        label_axes[i].axis[axisLoc].set_visible(False)
    label_axes[i].axis['bottom'].toggle(ticklabels=False)    

fig.subplots_adjust(wspace=-0.30, hspace=-0.30, left=0.00, right=0.99, top=0.99, bottom=0.0)
plt.show()

enter image description here

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