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?