Issue
I have a grid of subplots and I would like to adjust the white space between only two of them such that the shared x labels are centred without overlapping either graph.
This question has a solution for when these are the only two subplots. However I'm struggling to adjust this to two specific subplots in a grid of many.
This code can be used to illustrate my problem.
In [1]
fig = plt.figure(figsize = (15, 10))
gs = fig.add_gridspec(2,4)
ax1 = fig.add_subplot(gs[0, 0])
ax2 = fig.add_subplot(gs[0, 1:3])
ax3 = fig.add_subplot(gs[0, 3])
ax4 = fig.add_subplot(gs[1, 0])
ax5 = fig.add_subplot(gs[1, 1])
ax6 = fig.add_subplot(gs[1, 2])
ax7 = fig.add_subplot(gs[1, 3])
np.random.seed(19680801)
# Example data
people = ('Really Really Long Name', 'Another Long Name', 'Short Name', 'Name', 'N')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
ax5.barh(y_pos, performance, align='center')
ax5.set_yticks(y_pos, labels=people)
ax5.invert_xaxis()
ax5.set_xlabel('Label')
ax5.set_title('Bar 1')
ax6.barh(y_pos, performance, align='center')
ax6.set_yticks(y_pos, labels=people)
ax6.set_xlabel('Label')
ax6.set_title('Bar 2')
Out [1]
If I apply the solution to the linked question here then every subplot's white space is effected. I know this is because it calls on fig.dpi_scale_trans
which effects the whole figure but I'm new to transforms and can't work out what to use in its place
In [2]
fig.tight_layout()
fig.subplots_adjust(wspace=0.7)
plt.setp(axes[0].yaxis.get_majorticklabels(), ha='center')
# Create offset transform by some points in x direction
dx = 60 / 72.
dy = 0 / 72.
offset = mlb.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
# apply offset transform to all y ticklabels.
for label in ax6.yaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset)
Out [2]
Solution
I figured out how to solve this so posting my own answer in case anybody has a similar problem in the future.
This question and answer from 7 years ago contained the necessary help to solve the problem.
Essentially you must plot and position different GridSpecs in the figure using GridSpec
from matplotlib.gridspec
rather than calling one with fig.add_gridspec()
Link to GridSpec documentation
Following on from my example above I wanted to create a 2x4 grid. To do that we can plot the following grids in set positions of the figure:
Left: 1x2
Top Centre: 1x1
Bottom Centre: 2x1
Right: 1x2
In [1]:
from matplotlib.gridspec import GridSpec
fig = plt.figure(figsize = (15, 10))
# Example Data
people = ('Really Really Long Name', 'Another Long Name', 'Short Name', 'Name',
'N')
y_pos = np.arange(len(people))
performance = 3 + 10 * np.random.rand(len(people))
# Left portion of grid (2x1).
# 'left' and 'right' tell the grid where it should start and finish
gs1 = GridSpec(2, 1)
gs1.update(left = 0, right = 0.2)
# Plotting empty subplots for illustration purposes
for i in gs1:
ax = plt.subplot(i)
# Mirroring on the right portion of the grid
gs2 = GridSpec(2, 1)
gs2.update(left = 0.8, right = 1)
for i in gs2:
ax = plt.subplot(i)
# Plotting in top center
# Note here we only need to plot a 1x1
gs3 = GridSpec(1, 1)
gs3.update(left = 0.25, right = 0.75, bottom = 0.53) #0.53 aligns with sides
ax3 = plt.subplot(gs3[0])
# Plotting the barh in the bottom center
# wsapce only adjusts this grid not the entire figure
gs4 = GridSpec(1, 2)
gs4.update(left = 0.2, right = 0.8, top = 0.45, wspace = 0.75)
# Left barh
ax5 = plt.subplot(gs4[0])
ax5.barh(y_pos, performance, align='center')
ax5.set_yticks([])
ax5.invert_xaxis()
ax5.set_xlabel('Label')
ax5.set_title('Bar 1')
# Right barh
ax6 = plt.subplot(gs4[1])
ax6.barh(y_pos, performance, align='center')
ax6.set_yticks(y_pos, labels=people)
ax6.set_xlabel('Label')
ax6.set_title('Bar 2')
plt.show()
Out [1]:
Answered By - bjwphneb
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.