4

I need to remove the empty spaces between some subplots, by expanding the subplots horizontally.

Here's an image to show what I mean with two nice freehand red circles (MWE below):

enter image description here

By "get rid" I mean: expand horizontally the two bottom subplots in each column, so that there's little to no white space between them. The white space that separates the columns must remain untouched, to avoid modifying the square subplots above.

I've tried fig.subplots_adjust(wspace=0) but that messes up the above subplots, and I only need to modify the empty spaces between the bottom subplots.

I've also tried updating the GridSpec as shown here, but that doesn't get along with the tight_layout().


MWE

The MWE looks long but it's just the same code copy/pasted and with minor changes made (ie: removing ticks, labels, colorbar, etc).

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from mpl_toolkits.axes_grid1 import make_axes_locatable

fig = plt.figure(figsize=(14.25, 13.5))
gs = gridspec.GridSpec(3, 6)

# Left top plot.
ax1 = plt.subplot(gs[0:1, 0:2])
plt.title('AAAAAAAA', fontsize=11)
ax1.tick_params(axis='both', which='major', labelsize=9)
ax1.set_xticklabels([])
plt.xlabel('', fontsize=12)
plt.ylabel('BBBB', fontsize=12)
SC = plt.scatter([0., 1.], [0., 1.], c=[2., 5.])
# Position colorbar.
the_divider = make_axes_locatable(ax1)
color_axis = the_divider.append_axes("right", size="2%", pad=0.1)
# Colorbar.
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('ccc', fontsize=12, labelpad=4, y=0.5)
cbar.ax.tick_params(labelsize=9)
ax1.set_aspect(aspect='auto')

# Left middle plot.
ax2 = plt.subplot(gs[1:2, 0:2])
ax2.tick_params(axis='both', which='major', labelsize=9)
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('BBBB', fontsize=12)
SC = plt.scatter([10., 5.], [3., 17.], c=[0.3, 0.8])
the_divider = make_axes_locatable(ax2)
color_axis = the_divider.append_axes("right", size="2%", pad=0.1)
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('ccc', fontsize=12, labelpad=4, y=0.5)
cbar.ax.tick_params(labelsize=9)
ax2.set_aspect(aspect='auto')

# Left bottom left plot.
ax3 = plt.subplot(gs[2:3, 0:1])
ax3.tick_params(axis='both', which='major', labelsize=9)
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('BBBB', fontsize=12)

# Left bottom right pot.
ax4 = plt.subplot(gs[2:3, 1:2])
ax4.tick_params(axis='both', which='major', labelsize=9)
ax4.set_yticklabels([])
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('', fontsize=12)

# Middle top plot.
ax5 = plt.subplot(gs[0:1, 2:4])
plt.title('AAAAAAAA', fontsize=11)
ax5.tick_params(axis='both', which='major', labelsize=9)
ax5.set_xticklabels([])
ax5.set_yticklabels([])
plt.xlabel('', fontsize=12)
plt.ylabel('', fontsize=12)
SC = plt.scatter([0., 1.], [0., 1.], c=[2., 5.])
the_divider = make_axes_locatable(ax5)
color_axis = the_divider.append_axes("right", size="2%", pad=0.1)
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('ccc', fontsize=12, labelpad=4, y=0.5)
cbar.ax.tick_params(labelsize=9)
ax5.set_aspect(aspect='auto')

# Middle middle plot.
ax6 = plt.subplot(gs[1:2, 2:4])
ax6.tick_params(axis='both', which='major', labelsize=9)
ax5.set_yticklabels([])
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('', fontsize=12)
SC = plt.scatter([10., 5.], [3., 17.], c=[0.3, 0.8])
the_divider = make_axes_locatable(ax6)
color_axis = the_divider.append_axes("right", size="2%", pad=0.1)
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('ccc', fontsize=12, labelpad=4, y=0.5)
cbar.ax.tick_params(labelsize=9)
ax6.set_aspect(aspect='auto')

# Middle bottom left plot.
ax7 = plt.subplot(gs[2:3, 2:3])
ax7.tick_params(axis='both', which='major', labelsize=9)
ax7.set_yticklabels([])
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('', fontsize=12)

# Middle bottom right pot.
ax8 = plt.subplot(gs[2:3, 3:4])
ax8.tick_params(axis='both', which='major', labelsize=9)
ax8.set_yticklabels([])
plt.xlabel('DDDD', fontsize=12)
plt.ylabel('', fontsize=12)
SC = plt.scatter([10., 5.], [3., 17.], c=[0.3, 0.8])
the_divider = make_axes_locatable(ax8)
color_axis = the_divider.append_axes("right", size="5%", pad=0.1)
cbar = plt.colorbar(SC, cax=color_axis)
cbar.set_label('eee', fontsize=12, labelpad=4, y=0.5)
cbar.ax.tick_params(labelsize=9)

fig.tight_layout()
plt.savefig('del.png', dpi=150)
Community
  • 1
  • 1
Gabriel
  • 40,504
  • 73
  • 230
  • 404

1 Answers1

2

I managed to more or less solve the issue using several gridspecs and GridSpecFromSubplotSpec.

The code is rather horrendous and terribly hacky, but it gets the job done. I'll wait to see if someone comes up with a less terrible solution before accepting my answer.

enter image description here


Code:

import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from mpl_toolkits.axes_grid1 import make_axes_locatable
import numpy as np


def data():
    x = np.random.uniform(-10, 10., 50)
    y = np.random.uniform(-10, 10., 50)
    z = np.random.uniform(0, 1., 50)
    return x, y, z


def square_plot(gs, i):

    # Define gridspec ranges.
    x_gdsp = [[0, 2], [2, 4], [4, 6]]
    if i in [0, 1, 2]:
        y1, y2 = 0, 1
        x1, x2 = x_gdsp[i]
    elif i in [3, 4, 5]:
        y1, y2 = 1, 2
        x1, x2 = x_gdsp[i-3]

    ax = plt.subplot(gs[y1:y2, x1:x2])
    if i in [0, 1, 2]:
        plt.title('AAAAAAAA', fontsize=11)
        ax.set_xticklabels([])
    if i in [0, 3]:
        plt.ylabel('BBBB', fontsize=12)
    else:
        ax.set_yticklabels([])
    if i in [3, 4, 5]:
        plt.xlabel('CCCC', fontsize=12)
    ax.tick_params(axis='both', which='major', labelsize=9)
    x, y, z = data()
    SC = plt.scatter(x, y, c=z)
    # Position colorbar.
    the_divider = make_axes_locatable(ax)
    color_axis = the_divider.append_axes("right", size="2%", pad=0.1)
    # Colorbar.
    cbar = plt.colorbar(SC, cax=color_axis)
    cbar.set_label('cbar', fontsize=12, labelpad=4, y=0.5)
    cbar.ax.tick_params(labelsize=9)
    ax.set_aspect(aspect='auto')


def rectangular_plots(gs, i):

    x_gdsp = [[[0, 1], [2, 3], [4, 5]], [[1, 2], [3, 4],  [5, 6]]]
    y1, y2 = 2, 3
    x11, x12 = x_gdsp[0][i]
    x21, x22 = x_gdsp[1][i]

    # Left plot.
    right_gs = gridspec.GridSpecFromSubplotSpec(
        1, 2, width_ratios=[1, 6], subplot_spec=gs[y1:y2, x11:x12],
        wspace=0.)
    ax3 = plt.subplot(right_gs[1])
    plt.ylim(-15., 15.)
    plt.xlabel('DDDD', fontsize=12)
    if i == 0:
        ax3.set_ylabel('BBBB', fontsize=12)
    else:
        ax3.set_yticklabels([])
    ax3.tick_params(axis='both', which='major', labelsize=9)
    x, y, z = data()
    plt.scatter(x, y, c=z)

    # Right pot.
    right_gs = gridspec.GridSpecFromSubplotSpec(
        1, 2, width_ratios=[6, 1], subplot_spec=gs[y1:y2, x21:x22],
        wspace=0.)
    ax4 = plt.subplot(right_gs[0])
    plt.ylim(-15., 15.)
    plt.xlabel('DDDD', fontsize=12)
    ax4.tick_params(axis='both', which='major', labelsize=9)
    ax4.set_yticklabels([])
    x, y, z = data()
    SC = plt.scatter(x, y, c=z)
    the_divider = make_axes_locatable(ax4)
    color_axis = the_divider.append_axes("right", size="5%", pad=0.1)
    cbar = plt.colorbar(SC, cax=color_axis)
    cbar.set_label('eee', fontsize=12, labelpad=4, y=0.5)
    cbar.ax.tick_params(labelsize=9)


fig = plt.figure(figsize=(14.25, 13.5))

# Make square plots.
gs = gridspec.GridSpec(3, 6)
for i in range(6):
    square_plot(gs, i)

# New gridspecs for bottom rectangular plots.
# ***Values selected by hand***
gs2 = gridspec.GridSpec(3, 6)
gs2.update(wspace=0.0, bottom=0.029, left=0.031, right=0.95)
gs3 = gridspec.GridSpec(3, 6)
gs3.update(wspace=0.0, bottom=0.029, left=0.043, right=0.965)
gs4 = gridspec.GridSpec(3, 6)
gs4.update(wspace=0.0, bottom=0.029, left=0.05, right=0.976)

# Make plots.
rectangular_plots(gs2, 0)
rectangular_plots(gs3, 1)
rectangular_plots(gs4, 2)

fig.tight_layout()
plt.savefig('del.png', dpi=150)
Gabriel
  • 40,504
  • 73
  • 230
  • 404