mariofp77
mariofp77

Reputation: 135

One figure with two subplots and one with three do not have the same size

I am trying to create two figures with squared subfigures for an article. My problem is that when I do it for two subfigures I get one size and when I do it for three I get a different one, and I would like both to have the same overall size. Moreover, I would like to have all subfigures touching each other as in the examples below.

I am sharing the codes and the outputs for both cases.

Two subfigures:

fig, ax = plt.subplots(1,2, figsize=(13,7), sharey=True, facecolor='w')
fig.subplots_adjust(wspace=0, hspace=0)

ax[0].scatter(exp_list, yrel_slack_list, label='CCC; R$^2$ = 0.34, MUE = 1.01')
ax[0].scatter(exp_list, yrel_glm1_list, facecolors='none', edgecolors='#ff7f0e', label='CCC + cGLM1; R$^2$ = 0.81, MUE = 0.56')
ax[0].plot(np.linspace(-4,4), np.linspace(-4,4), color='red')

ax[1].scatter(exp_list, yrel_slack_list, label='CCC; R$^2$ = 0.34, MUE = 1.01')
ax[1].scatter(exp_list, yrel_slm1_list, facecolors='none', edgecolors='#8c564b', label='CCC + cSLM1; R$^2$ = 0.40, MUE = 0.77')
ax[1].plot(np.linspace(-4,4), np.linspace(-4,4), color='red')

ax[0].set_ylabel(r'Estimated $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax[0].set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax[0].legend(loc=0, frameon=False, fontsize=14, handletextpad=0.1)
ax[0].set_ylim([-4,1])
ax[0].set_xlim([-4,1])
ax[0].set_xticks([-4, -3, -2, -1, 0])
ax[0].tick_params(axis = 'both', which = 'major', labelsize=14)
ax[1].set_xlim([-4,1])
ax[1].legend(loc=0, frameon=False, fontsize=14, handletextpad=0.1)
ax[1].set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax[1].tick_params(axis = 'both', which = 'major', labelsize=14)

plt.savefig('inclusion_1h1q_correlation.eps', format='eps', bbox_inches='tight')
plt.show()

enter image description here

Three subfigures:

fig, ax = plt.subplots(1,3, figsize=(20,7), sharey=True, facecolor='w')
fig.subplots_adjust(wspace=0, hspace=0)

ax[0].scatter(exp_list, yrel_slack_list, marker='x', color='k', label='CCC; R$^2$ = 0.34, MUE = 1.01')
ax[0].scatter(exp_list, yrel_c1oiu1h1q_list, color='#1f77b4', label='CCC + cGLM1; R$^2$ = %.2f, MUE = %.2f'%(corr_node_c1oiu1h1q[0]**2,corr_node_c1oiu1h1q[1]))
ax[0].plot(np.linspace(-4,1), np.linspace(-4,1), color='red')

ax[1].scatter(exp_list, yrel_slack_list, marker='x', color='k', label='CCC; R$^2$ = 0.34, MUE = 1.01')
ax[1].scatter(exp_list, yrel_c1oiu1h1q_c1oiu1h1s_list, color='#ff7f0e', label='CCC + cGLM1-2; R$^2$ = %.2f, MUE = %.2f'%(corr_node_c1oiu1h1q_c1oiu1h1s[0]**2,corr_node_c1oiu1h1q_c1oiu1h1s[1]))
ax[1].plot(np.linspace(-4,1), np.linspace(-4,1), color='red')

ax[2].scatter(exp_list, yrel_slack_list, marker='x', color='k', label='CCC; R$^2$ = 0.34, MUE = 1.01')
ax[2].scatter(exp_list, yrel_c1h1q1oiu_i1oiu_list, color='#2ca02c', label='CCC + cGLM1 + iGLMI1; R$^2$ = %.2f, MUE = %.2f'%(corr_node_1oiu[0]**2,corr_node_1oiu[1]))
ax[2].plot(np.linspace(-4,1), np.linspace(-4,1), color='red')

ax[0].set_ylabel(r'Estimated $\Delta \Delta G$ (kcal/mol)', fontsize=18)
ax[0].set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=18)
ax[0].legend(loc=0, frameon=False, fontsize=12, handletextpad=0.1)
ax[0].set_ylim([-3.5,1])
ax[0].set_xlim([-3.5,1])
ax[0].tick_params(axis = 'both', which = 'major', labelsize=18)
ax[1].set_xlim([-3.5,1])
ax[1].legend(loc=0, frameon=False, fontsize=12, handletextpad=0.1)
ax[1].set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=18)
ax[1].tick_params(axis = 'both', which = 'major', labelsize=18)
ax[2].set_xlim([-3.5,1])
ax[2].legend(loc=0, frameon=False, fontsize=12, handletextpad=0.1)
ax[2].set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=18)
ax[2].tick_params(axis = 'both', which = 'major', labelsize=18)

plt.savefig('main_result_cdk2.eps', format='eps', bbox_inches='tight')
plt.show()

enter image description here

Upvotes: 2

Views: 121

Answers (1)

MagnusO_O
MagnusO_O

Reputation: 1283

You can use gridspec to align subplots ratios for a given overall figure size incl. your required y-axis touching.

I haven't adapted all your various individual plot settings, but tried to show how gridspec can be used for your general case and kept the respective parts like e.g. the axis ticks (to not overlap especially at the shared y-axis).

from matplotlib import gridspec

### 2 subplots
fig = plt.figure(figsize=(20,7), facecolor='w')
fig.subplots_adjust(wspace=0, hspace=0)

gs = gridspec.GridSpec(1, 2, width_ratios=[1,1]) 
ax1 = fig.add_subplot(gs[0,:1])
ax1.set_title('ax1')
ax1.set_ylim([-4,1])
ax1.set_xlim([-4,1])
ax1.set_xticks([-4, -3, -2, -1, 0])

xx, locs = plt.yticks()
ll = ['%.1f' % a for a in xx]
ax1.set_yticks(xx, ll)

ax1.tick_params(axis = 'both', which = 'major', labelsize=14)
ax2 = fig.add_subplot(gs[0,1:])
ax2.set_title('ax2')
ax2.get_yaxis().set_visible(False)
ax2.set_xlim([-4,1])
ax2.tick_params(axis = 'both', which = 'major', labelsize=14)

ax1.set_ylabel(r'Estimated $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax1.set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax2.set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)

plt.show()

### 3 subplots
fig = plt.figure(figsize=(20,7), facecolor='w')
fig.subplots_adjust(wspace=0, hspace=0)

gs = gridspec.GridSpec(1, 3, width_ratios=[1,1,1]) 
ax1 = fig.add_subplot(gs[0,:1])
ax1.set_title('ax1')
ax1.set_ylim([-3.5,1])
ax1.set_xlim([-3.5,1])
ax1.tick_params(axis = 'both', which = 'major', labelsize=14)
ax2 = fig.add_subplot(gs[0,1])
ax2.set_title('ax2')
ax2.get_yaxis().set_visible(False)
ax2.set_xlim([-3.5,1])
ax2.tick_params(axis = 'both', which = 'major', labelsize=14)
ax3 = fig.add_subplot(gs[0,2:])
ax3.set_title('ax3')
ax3.get_yaxis().set_visible(False)
ax3.set_xlim([-3.5,1])
ax3.tick_params(axis = 'both', which = 'major', labelsize=14)

ax1.set_ylabel(r'Estimated $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax1.set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax2.set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)
ax3.set_xlabel('Experimental $\Delta \Delta G$ (kcal/mol)', fontsize=14)

plt.show()

Notes:

  • The inner y-axes need the set_visible(False)
  • With figsize=(20,7) on top you can adapt the overal plot size
    • You may align that if you need more squared subplots and accept different heights for that at a given overall width.
  • If you want to keep the ticks on the connected y-axes but only want to remove the label you can replace ax2.get_yaxis().set_visible(False) by ax2.tick_params(axis='y', label1On=False)
  • Items to fine tune the optical width on the left y-axis - adapt those acc. your preference.
    • I notized you had different font sizes and aligned them.
    • At the 2 subplots y-axis floats with 1 decimal point is included (as given by the 3 subplots y-axis), you can remove that part again easily if it's not intended.

Here's a screenshot incl. some jupyter parts to show that both overall plots have the same size:

enter image description here

Upvotes: 1

Related Questions