0

I'm trying to save a figure created using subplots_mosaics that has twin y-axes scales. The ylabel on the right always gets either trimmed off or written over the ytick labels when I save - although I have got this to work with plt.show()

import matplotlib.pyplot as plt
import numpy as np


# Functions to plot data
def plot_bar_timeseries(x, y, colour, ax=None, label=None):
    ax.bar(x, y, width=1, color=colour, label=label)
    return ax

def plot_line_timeseries(x, y, colour, style, ax=None, label=None):
    ax.plot(x, y, style, c=colour, label=label)
    return ax


# Create figure and axes using subplots_mosaic
fig, axs = plt.subplot_mosaic([['1'],
                               ['2'],
                               ['2'],
                               ['3'],
                               ['3']],
                              layout='constrained', figsize=(16, 12), dpi=600, sharex=True)

# Example data to be used
x_data = np.reshape(np.linspace(0, 12, 13), (-1, 1))
y1_data = np.random.rand(13, 1)
y2_L_data = np.random.rand(13, 1)
y2_R_data = np.random.rand(13, 1)*10

# create shared axes due to scale mismatch between y2_L and y2_R
axshare2 = axs['2'].twinx()
axshare3 = axs['3'].twinx()

#plots top plot
axs['1'] = plot_bar_timeseries(x_data[:,0], y1_data[:,0], 'blue', axs['1'])
axs['1'].set_ylabel('y1_label')


# plots up the lower two plots, both left and right y-axes
ax_plot_list = ['2', '3']
ax_share_dict = {'2':axshare2, '3':axshare3}

for ax_id in range(len(ax_plot_list)):
    axs[ax_plot_list[ax_id]] = plot_line_timeseries(x_data, y2_L_data, 'green', '-', axs[ax_plot_list[ax_id]])
    ax_share_dict[ax_plot_list[ax_id]] = plot_line_timeseries(x_data, y2_R_data, 'red', '-', ax_share_dict[ax_plot_list[ax_id]])

# heres my x-label...the subplots share x
axs['3'].set_xlabel('x label')


# here's my shared left-hand y-label for the lower two plots ['2'] and ['3]
ax_a = fig.add_subplot(1,1,1)
ax_a.set_xticks([])
ax_a.set_yticks([])
[ax_a.spines[side].set_visible(False) for side in ('left', 'top', 'right', 'bottom')]
ax_a.patch.set_visible(False)
ax_a.yaxis.set_label_position('left')
ax_a.set_ylabel('y2_Left_label)')

Now here's the issue, the right-hand y-label for the lower plots...

I have tried the following:

ax_b = fig.add_subplot(1,1,1)
ax_b.set_xticks([])
ax_b.set_yticks([])
[ax_b.spines[side].set_visible(False) for side in ('left', 'top', 'right', 'bottom')]
ax_b.patch.set_visible(False)
ax_b.yaxis.set_label_position('right')
ax_b.set_ylabel('y2_right_label', labelpad=30)

Which doesn't work, as it plots the ylabel over the ytick label.

I've also tried this:

fig.supylabel('y2_right_label', x=1.01, y=0.5)

Which works fine with plt.show()

But gets trimmed off using fig.savefig() and plt.savefig()

Does anyone have any thoughts?

Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
georussell
  • 302
  • 1
  • 10

0 Answers0