matplotlib: tight_layout с более чем 4 осями Twinx имеет дополнительное заполнение

Я запускаю скрипт для построения набора до 6 кривых, имеющих общую временную шкалу. Я использую twinx() до 5 раз и получаю до 4 отдельных осей с правой стороны графика. Сценарий (показан ниже) взят из этого примера. Однако рецепт рисования дополнительных осей, показанный в этом примере, не работает, если у меня есть более одной дополнительной оси. Чтобы нарисовать дополнительные оси, я должен использовать plt.tight_layout(). Но когда я это делаю, я получаю чрезмерное отступы, в основном в правой части графика, что значительно снижает возможность отображения красиво расположенных кривых, даже при расширении окна отображения, как показано на этом снимке: результат скрипта Я не получаю дополнительное дополнение, когда не использую tight_layout, но тогда я не вижу дополнительные оси. Я попробовал несколько рецептов восстановления отображения дополнительных осей на основе кода в указанном примере, о чем свидетельствуют фрагменты закомментированного кода в моем сценарии, но безрезультатно.

Как мне избавиться от этого дополнительного заполнения и одновременно увидеть мои дополнительные оси?

Скрипт:

#!/usr/bin/env python3
import matplotlib.pyplot as plt
import matplotlib as mpl
x_data1=[234.5, 242.9, 251.4, 259.8, 268.2, 276.7, 285.1, 293.5, 339.7, 341.5, 343.4, 345.3, 347.2, 349.1, 351.0, 352.9, 354.8, 356.7, 358.6, 360.5, 362.4, 364.2, 366.1, 368.0, 370.0, 372.2, 374.5, 377.3, 381.7, 386.1, 390.6, 396.0, 401.4, 406.8, 409.8, 412.0, 414.3, 416.5, 437.6, 441.8, 446.0, 450.2, 454.4, 458.5, 462.7, 466.9, 471.1, 475.3, 479.5, 483.7, 487.9, 492.0, 496.2, 500.4, 504.6, 508.8, 513.0, 517.2, 521.3, 525.5, 529.7, 533.9, 538.1, 542.3, 607.5, 612.5, 617.5, 622.5, 627.6, 632.6, 637.6, 642.2, 646.6, 651.0, 655.5, 659.9, 664.4, 668.8, 673.2, 677.7, 682.1, 686.5, 691.0, 695.4, 699.9, 704.3, 708.7, 712.4, 715.9, 719.3, 722.8, 726.9]
y_data1=[229.0, 415.0, 399.0, 399.0, 399.0, 280.0, 257.0, 256.0, 172.0, 82.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 61.0, 58.0, 21.0, 16.0, 16.0, 16.0, 16.0, 17.0, 17.0, 17.0, 17.0, 19.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 17.0, 153.0, 151.0, 150.0, 150.0, 154.0, 154.0, 154.0, 154.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 83.0, 86.0, 94.0, 91.0, 96.0, 95.0]
x_data2=[234.5, 242.9, 251.4, 259.8, 268.2, 276.7, 285.1, 293.5, 339.7, 341.5, 343.4, 345.3, 347.2, 349.1, 351.0, 352.9, 354.8, 356.7, 358.6, 360.5, 362.4, 364.2, 366.1, 368.0, 370.0, 372.2, 374.5, 377.3, 381.7, 386.1, 390.6, 396.0, 401.4, 406.8, 409.8, 412.0, 414.3, 416.5, 437.6, 441.8, 446.0, 450.2, 454.4, 458.5, 462.7, 466.9, 471.1, 475.3, 479.5, 483.7, 487.9, 492.0, 496.2, 500.4, 504.6, 508.8, 513.0, 517.2, 521.3, 525.5, 529.7, 533.9, 538.1, 542.3, 607.5, 612.5, 617.5, 622.5, 627.6, 632.6, 637.6, 642.2, 646.6, 651.0, 655.5, 659.9, 664.4, 668.8, 673.2, 677.7, 682.1, 686.5, 691.0, 695.4, 699.9, 704.3, 708.7, 712.4, 715.9, 719.3, 722.8, 726.9]
y_data2=[180857.0, 363307.0, 329311.0, 326878.0, 335580.0, 317721.0, 310990.0, 320455.0, 63791.0, 28188.0, 2225.0, 1185.0, 1169.0, 1119.0, 1107.0, 1102.0, 1060.0, 1064.0, 964.0, 935.0, 876.0, 844.0, 785.0, 786.0, 790.0, 112.0, 28.0, 16.0, 16.0, 16.0, 50.0, 50.0, 50.0, 50.0, 22.0, 18.0, 18.0, 17.0, 264.0, 264.0, 251.0, 245.0, 244.0, 244.0, 247.0, 241.0, 264.0, 250.0, 239.0, 243.0, 244.0, 244.0, 269.0, 273.0, 266.0, 266.0, 266.0, 266.0, 266.0, 266.0, 266.0, 267.0, 267.0, 267.0, 9176.0, 67583.0, 49187.0, 48926.0, 59661.0, 54753.0, 59591.0, 58931.0, 35613.0, 32199.0, 30769.0, 30220.0, 28164.0, 24589.0, 23711.0, 23711.0, 19949.0, 20236.0, 20238.0, 21827.0, 22666.0, 22666.0, 22666.0, 23609.0, 28585.0, 33004.0, 33649.0, 32913.0]
x_data3=[339.7, 341.5, 343.4, 345.3, 347.2, 349.1, 351.0, 352.9, 354.8, 356.7, 358.6, 360.5, 362.4, 364.2, 366.1, 368.0, 370.0, 372.2, 374.5, 377.3, 381.7, 386.1, 390.6, 396.0, 401.4, 406.8, 409.8, 412.0, 414.3, 416.5, 437.6, 441.8, 446.0, 450.2, 454.4, 458.5, 462.7, 466.9, 471.1, 475.3, 479.5, 483.7, 487.9, 492.0, 496.2, 500.4, 504.6, 508.8, 513.0, 517.2, 521.3, 525.5, 529.7, 533.9, 538.1, 542.3, 607.5, 612.5, 617.5, 622.5, 627.6, 632.6, 637.6, 642.2, 646.6, 651.0, 655.5, 659.9, 664.4, 668.8, 673.2, 677.7, 682.1, 686.5, 691.0, 695.4, 699.9, 704.3, 708.7, 712.4, 715.9, 719.3, 722.8, 726.9]
y_data3=[1661870.0, 1662180.0, 1662330.0, 1662390.0, 1667640.0, 1672780.0, 1677880.0, 1682720.0, 1687830.0, 1692960.0, 1697780.0, 1702610.0, 1707020.0, 1711770.0, 1715340.0, 1715620.0, 1715620.0, 1715670.0, 1715700.0, 1715700.0, 1714460.0, 1706260.0, 1697080.0, 1696900.0, 1694770.0, 1689730.0, 1690880.0, 1691670.0, 1692840.0, 1692860.0, 1692860.0, 1691270.0, 1692140.0, 1693570.0, 1694640.0, 1695590.0, 1696470.0, 1697190.0, 1697790.0, 1698290.0, 1698730.0, 1699100.0, 1699380.0, 1699660.0, 1700020.0, 1700210.0, 1700560.0, 1700580.0, 1700580.0, 1700590.0, 1700590.0, 1700600.0, 1700600.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700610.0, 1700560.0, 1700570.0, 1700920.0, 1701290.0, 1701890.0, 1702220.0, 1702250.0, 1702250.0, 1702250.0, 1702250.0, 1702190.0, 1702470.0, 1702650.0, 1702700.0, 1702700.0, 1702700.0, 1702700.0, 1702700.0, 1702700.0, 1702700.0]
x_data4=[18.4, 236.6, 245.0, 253.5, 261.9, 270.4, 278.8, 287.2, 295.6, 340.1, 342.0, 343.9, 345.8, 347.7, 349.6, 351.5, 353.4, 355.3, 357.2, 359.0, 360.9, 362.8, 364.7, 366.6, 368.5, 370.6, 372.8, 375.0, 378.4, 382.8, 387.2, 391.9, 397.3, 402.7, 408.1, 410.4, 412.6, 414.8, 417.1, 438.7, 442.8, 447.0, 451.2, 455.4, 459.6, 463.8, 468.0, 472.2, 476.3, 480.5, 484.7, 488.9, 493.1, 497.3, 501.5, 505.6, 509.8, 514.0, 518.2, 522.4, 526.6, 530.8, 534.9, 539.1, 543.3, 608.7, 613.8, 618.8, 623.8, 628.8, 633.8, 638.8, 643.3, 647.7, 652.1, 656.6, 661.0, 665.5, 669.9, 674.3, 678.8, 683.2, 687.7, 692.1, 696.5, 701.0, 705.4, 709.8, 713.3, 716.8, 720.2, 723.7, 840.1]
y_data4=[0.0124657, 0.012522, 0.0882, 0.1029, 0.1029, 0.0737, 0.0809, 0.0813, 0.0649, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.019607, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.149659, 0.158997, 0.1891, 0.1968, 0.1968, 0.1219, 0.1223, 0.0879, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.0193957, 0.1515, 0.1045, 0.0861, 0.0755, 0.0169167]
x_data5=[437.6, 441.8, 446.0, 450.2, 454.4, 458.5, 462.7, 466.9, 471.1, 475.3, 479.5, 483.7, 487.9, 492.0, 496.2, 500.4, 504.6, 508.8, 513.0, 517.2, 521.3, 525.5, 529.7, 533.9, 538.1, 542.3, 607.5, 612.5, 617.5, 622.5, 627.6, 632.6, 637.6, 642.2, 646.6, 651.0, 655.5, 659.9, 664.4, 668.8, 673.2, 677.7, 682.1, 686.5, 691.0, 695.4, 699.9, 704.3, 708.7, 712.4, 715.9, 719.3, 722.8, 726.9]
y_data5=[244.0, 244.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 191.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 160.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 164.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0, 22.0]
x_data6=[437.6, 441.8, 446.0, 450.2, 454.4, 458.5, 462.7, 466.9, 471.1, 475.3, 479.5, 483.7, 487.9, 492.0, 496.2, 500.4, 504.6, 508.8, 513.0, 517.2, 521.3, 525.5, 529.7, 533.9, 538.1, 542.3, 607.5, 612.5, 617.5, 622.5, 627.6, 632.6, 637.6, 642.2, 646.6, 651.0, 655.5, 659.9, 664.4, 668.8, 673.2, 677.7, 682.1, 686.5, 691.0, 695.4, 699.9, 704.3, 708.7, 712.4, 715.9, 719.3, 722.8, 726.9]
y_data6=[949459.0, 949459.0, 804920.0, 607955.0, 465419.0, 357145.0, 273773.0, 201022.0, 147651.0, 108046.0, 77119.0, 53458.0, 36383.0, 25208.0, 17901.0, 16613.0, 893.0, 865.0, 853.0, 840.0, 829.0, 824.0, 819.0, 401.0, 398.0, 398.0, 398.0, 398.0, 398.0, 398.0, 398.0, 398.0, 398.0, 21560.0, 21762.0, 21762.0, 21741.0, 21740.0, 21738.0, 21662.0, 21654.0, 21695.0, 21736.0, 21739.0, 21739.0, 4865.0, 847.0, 204.0, 198.0, 198.0, 198.0, 198.0, 198.0, 198.0]
def make_patch_spines_invisible(ax):
    ax.set_frame_on(True)
    ax.patch.set_visible(False)
    for sp in ax.spines.values():
        sp.set_visible(False)

def patch_detached_spines(ax_list):
    for ax in ax_list:
        ax.set_frame_on(True)
    for ax in ax_list:
        ax.patch.set_visible(False)
    for ax in ax_list:
        for sp in ax.spines.values():
            sp.set_visible(False)
    for ax in ax_list:
        ax.spines['right'].set_visible(True)

def run_one_plot(x_data, y_data, fig, host, key, label, color_and_style, axis_offset, lines, detached_spine_plots):
    tkw = dict(size=4,width=1.5)
    if axis_offset > 0.8:
        plot = host.twinx()
    else:
        plot = host
    if axis_offset > 1.0:
        detached_spine_plots.append(plot)
    if key == 'TTT' or key == 'HHH':
        plot.set_yscale('log')
    if axis_offset > 1.0:
        plot.spines['right'].set_position(('axes', axis_offset))
        #make_patch_spines_invisible(plot)
        #plot.spines['right'].set_visible(True)
    p, = plot.plot(x_data, y_data, color_and_style, label=label)
    if axis_offset == 0.8:
        plot.set_ylabel(label)
    else:
        plot.text(axis_offset, 0, label, ha="left", va="top", rotation=90, transform=host.transAxes)
    lines.append(p)
    plot.yaxis.label.set_color(p.get_color())
    plot.tick_params(axis='y', colors=p.get_color(),**tkw)


fig, host = plt.subplots()
host.set_xlabel('Time (minutes)')
x_ticks = [18.366666666666667, 232.4, 295.8, 339.18333333333334, 376.1666666666667, 408.1166666666667, 417.65, 436.56666666666666, 544.3666666666667, 606.2333333333333, 641.05, 724.6666666666666]
x_labels = ['[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]']
plt.xticks(x_ticks,x_labels,rotation='vertical')
plt.tick_params(axis='x', which='both', labelsize = 6)
lines = []
detached_spine_plots = []
extra_axis_offset = 0.8

run_one_plot(x_data1, y_data1, fig, host, 'AAA', 'AAA', "b+", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset = 1.0

run_one_plot(x_data2, y_data2, fig, host, 'TTT', 'TTT', "rs", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset+=0.2

run_one_plot(x_data3, y_data3, fig, host, 'AAAA', 'AAAA', "g^", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset+=0.2

run_one_plot(x_data4, y_data4, fig, host, 'OOOOOOOOOOO', 'GGGGGGGGGG', "ko", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset+=0.2

run_one_plot(x_data5, y_data5, fig, host, 'WWW', 'WWW', "c.", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset+=0.2

run_one_plot(x_data6, y_data6, fig, host, 'HHH', 'HHH', "mx", extra_axis_offset, lines, detached_spine_plots)
extra_axis_offset+=0.2

host.legend(lines, [l.get_label() for l in lines])
#patch_detached_spines(detached_spine_plots)
fig.tight_layout(pad=0)
plt.show()

person LMNCA    schedule 18.02.2019    source источник
comment
что произойдет, если вы удалите tight_layout, но вместо этого сохраните фигуру, используя bbox_inches='tight'? Кроме того, пожалуйста, также опубликуйте свой код как суть, потому что его действительно сложно скопировать и вставить точно.   -  person story645    schedule 18.02.2019
comment
Единственный шанс, который у вас есть в настоящее время, - это определить интервал вручную. В самом простом случае просто добавьте fig.subplots_adjust(right=0.6) между tight_layout и show и играйте с числом 0.6, пока не будете удовлетворены.   -  person ImportanceOfBeingErnest    schedule 19.02.2019
comment
Если я удалю tight_layout и использую bbox_inches='tight' (сделал это, добавив fig.savefig('xx',bbox_inches='tight')) я все равно получаю только одну ось справа. Схема «subplot_adjust», кажется, работает, и я могу избавиться от обходных путей bbox_inches='tight' и tight_layout, чтобы увидеть дополнительные оси, поэтому я думаю, что я пойду с этим.   -  person LMNCA    schedule 19.02.2019
comment
Однако, не желая быть злым, я просто применяю рецепты, которые вы мне даете, не понимая, почему и как это все работает. За исключением чтения кода реализации, где я могу найти хороший ресурс о том, как управлять относительным расположением фигуры, осей и связанных аннотаций, а также любых добавленных дополнений?   -  person LMNCA    schedule 19.02.2019
comment
Многие подобные вещи описаны в matplotlib.org/tutorials/intermediate/   -  person story645    schedule 20.02.2019


Ответы (2)


Использование всего, что устанавливает bbox_inches='tight' (в том числе в качестве аргумента fig.savefig), создает следующую фигуру: add

person story645    schedule 18.02.2019
comment
только что обновил изображение, которое я попробовал. Как будто изображение все еще слишком загромождено, но это потому, что ему нужен больший размер и пользовательские / ручные галочки. - person story645; 19.02.2019
comment
Вероятно, вы создали это изображение в jupyter и, следовательно, с активированной опцией bbox_inches="tight", что означает, что вы должны получить то же изображение с constrained_layout=False, верно? - person ImportanceOfBeingErnest; 19.02.2019
comment
Я думаю, что есть даже очень фундаментальная проблема с constrained_layout в таком случае, когда что-то позиционируется в координатах осей, потому что размер осей зависит от вспомогательного художника, который позиционируется в координатах осей и, следовательно, зависит от размера осей. Я полагаю, что разрешить такое круговое ограничение практически невозможно. - person ImportanceOfBeingErnest; 19.02.2019
comment
есть открытый вопрос по этому поводу? - person story645; 19.02.2019
comment
Я так не думаю, но этот комментарий может быть близок к Это. - person ImportanceOfBeingErnest; 19.02.2019
comment
В моей установленной версии matplotlib нет «constrained_layout». К сожалению, я не могу изменить это так просто, потому что это корпоративная установка, и ее обновление потребует долгих недель и большого количества документов. Я пробовал с bbox_inches=tight, как было предложено, но без constrained_layout, конечно, и я больше не вижу отступов с левой стороны, но отступы с правой стороны еще больше (более 1/3 ширины) . - person LMNCA; 19.02.2019

Что сработало для меня, так это применить предложение @ImportanceOfBeingErnest об использовании fig.subplots_adjust(right=). Моя версия matplotlib, похоже, ничего не знает о constrained_layout, поэтому для меня предложение @story645 объединить эту опцию с bbox_inches="tight" не сработало.

person LMNCA    schedule 22.02.2019