3

I am thinking on a plot that contains 3 rows and 4 columns, where:

There are 3 dependent variables to plot: Y1, Y2 and Y3, versus a common X independent variable, for 4 cases of study:

enter image description here

In this situation there is:

1) a sharing of y axis when going from case i to case i+1

2) a sharing of x axis within a case i

Thus, in principle, one would think that the following code will produce the desired plot (result shown in the upper image):

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex=True, sharey=True,\
                         subplot_kw=dict(adjustable='box-forced'))

where the adjustable='box-forced' is just to ensure that the subplots are squared, as explained here.

When I try to plot Y1 versus X for case 1:

import numpy as np
import matplotlib.pyplot as plt
import sys

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex=True, sharey=True,\
                         subplot_kw=dict(adjustable='box-forced'))

pad = 5
axes[0][0].annotate('Case 1', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

axes[0][1].annotate('Case 2', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

axes[0][2].annotate('Case 3', xy=(0.5, 1), xytext=(0, pad),
               xycoords='axes fraction', textcoords='offset points',
                size='large', ha='center', va='baseline')

axes[0][3].annotate('Case 4', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

#
axes[0][0].set_ylabel('Y1', fontsize=10)
axes[1][0].set_ylabel('Y2', fontsize=10)
axes[2][0].set_ylabel('Y3', fontsize=10)

E_C_I =  np.array([-941.23658347, -941.23685494, -941.23467666])
V_C_I =  np.array([ 61.66341, 62.342903,  67.9311515])
E_14 =  np.array([-941.22938469, -941.23583586, -941.23605613])
V_14 =  np.array([ 54.65693125,  58.47115725, 60.8626545 ])
P_C_I =  np.array([ 2.20068119,  1.33328211,  -4.28370285])
P_14 =  np.array([ 8.16605135,  7.54737315, 0.3909309 ])


axes[0][0].scatter(V_C_I, E_C_I, marker='^', color='red', label='Calcite I')#, s=100)
axes[0][0].scatter(V_14, E_14, marker='o', color='green', label='Calcite I')#, s=100)

axes[0][0].set_ylim(bottom=-941.238, top=-941.229)

plt.tight_layout()
axes[0][0].ticklabel_format(useOffset=False)
plt.show()
sys.exit()

Everything seems fine:

enter image description here

I have forced the plot to axes[0][0].set_ylim(bottom=-941.238, top=-941.229)

When I try to plot Y2 versus X for Case 1, the following code should work: I am basically doing the same as before, but adding the axes[1][0] plotting instruction:

import numpy as np
import matplotlib.pyplot as plt
import sys

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex=True, sharey=True,\
                         subplot_kw=dict(adjustable='box-forced'))

pad = 5
axes[0][0].annotate('Case 1', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

axes[0][1].annotate('Case 2', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

axes[0][2].annotate('Case 3', xy=(0.5, 1), xytext=(0, pad),
               xycoords='axes fraction', textcoords='offset points',
                size='large', ha='center', va='baseline')

axes[0][3].annotate('Case 4', xy=(0.5, 1), xytext=(0, pad),
                xycoords='axes fraction', textcoords='offset points',
                 size='large', ha='center', va='baseline')

#
axes[0][0].set_ylabel('Y1', fontsize=10)
axes[1][0].set_ylabel('Y2', fontsize=10)
axes[2][0].set_ylabel('Y3', fontsize=10)

E_C_I =  np.array([-941.23658347, -941.23685494, -941.23467666])
V_C_I =  np.array([ 61.66341, 62.342903,  67.9311515])
E_14 =  np.array([-941.22938469, -941.23583586, -941.23605613])
V_14 =  np.array([ 54.65693125,  58.47115725, 60.8626545 ])
P_C_I =  np.array([ 2.20068119,  1.33328211,  -4.28370285])
P_14 =  np.array([ 8.16605135,  7.54737315, 0.3909309 ])


axes[0][0].scatter(V_C_I, E_C_I, marker='^', color='red', label='Calcite I')#, s=100)
axes[0][0].scatter(V_14, E_14, marker='o', color='green', label='Calcite I')#, s=100)

axes[0][0].set_ylim(bottom=-941.238, top=-941.229)

axes[1][0].scatter(V_C_I, P_C_I, marker='^', color='red', label='Calcite I')#, s=100)
axes[1][0].scatter(V_14, P_14, marker='o', color='green', label='Calcite I')#, s=100)

axes[1][0].set_ylim(bottom=-4.4, top=8.4)

plt.tight_layout()
axes[0][0].ticklabel_format(useOffset=False)
plt.show()
sys.exit()

The result is that the axes[0][0] plot has changed its scale, and therefore no data is shown:

enter image description here

I have forced both axes[0][0] and axes[0][1] to show the region where indeed there is data:

axes[0][0].set_ylim(bottom=-941.238, top=-941.229)
axes[1][0].set_ylim(bottom=-4.4, top=8.4)

However, no data is shown on the axes[0][0] plot. Why is this happening?

Update: The difference between sharey='row' and sharey=True has been clarified in the excellent @DavidG's answer. However, I have tested the difference between sharex='col' and sharex=True and I have noticed that:

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex=True, sharey='row',\
                         subplot_kw=dict(adjustable='box-forced'))

produces the following:

enter image description here

However,

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex='col', sharey='row',\
                         subplot_kw=dict(adjustable='box-forced'))

kind of leaves some space between the columns, and breaks the adjustable='box-forced' declaration for the subplots to be squared:

enter image description here

I was wondering why this is happening?

DavidC.
  • 669
  • 8
  • 26

1 Answers1

2

You have applied the share y axis to all of the subplots using the argument sharey=True.

There is a handy argument of sharey='row' which will make each row of subplots share the same y axis. Therefore, change the creating of the figure to:

fig, axes = plt.subplots(ncols=4, nrows=3,\
                         sharex=True, sharey='row',\
                         subplot_kw=dict(adjustable='box-forced'))

This will then give the following figure:

enter image description here

DavidG
  • 24,279
  • 14
  • 89
  • 82
  • Thanks a lot for your answer. You have very well pointed out the difference between `sharey='row'` and `sharey=True`. However, I have noticed that the difference between `sharex=True` and `sharex='col'` produces kind of a different result (please see updated post). – DavidC. May 21 '18 at 09:13
  • I have changed the title of the post, so that it is presented as a more general case – DavidC. May 24 '18 at 19:44