1

As you can see on the image below, my entire plot (whether it's the heatmaps, the title or the colorbar) is “tighten” in the top of the figure/window and there is a large blank space in the bottom

The figure I get

Is there a way to lower it entirely AND to reduce the blank space in the bottom?

I've already tried to use the fig.tight_layout() and to change the values of the figsize argument of the plt.figurefunction but the space in the bottom stays the same (proportionally)...

Here is the piece of code:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1 import AxesGrid



def graphs():
    fig = plt.figure(figsize=(13.5, 6.8))
    Grid = AxesGrid(fig, 111, nrows_ncols=(1,3), axes_pad=0.2, share_all=False, label_mode='L', cbar_location="bottom", cbar_mode="single")

    Matrices = [np.random.randint(-100,10,(10,10)) for i in range(3)]
    M, m = np.max(Matrices), np.min(Matrices)

    for values, ax in zip(Matrices, Grid):

        ax.tick_params(top = True, bottom = False, labeltop = True, labelbottom = False)
        ax.xaxis.set_label_position('top')

        heatmap = ax.imshow(values, vmin=m, vmax=M, cmap='plasma')
        ax.set_xticks(np.arange(0,10), labels=list(np.arange(1,11)), fontsize=6)
        ax.set_xlabel('Arrival', fontweight='bold', fontsize=8)
        plt.setp(ax.get_xticklabels(), rotation=35, ha="center", rotation_mode=None)

        for l in range(len(values)):
            for c in range(len(values[l])):
                text = ax.text(c, l, values[l,c], ha="center", va="center", color='k', fontsize=6)

        ax.set_title('Gaps', fontweight='bold', fontsize=9)

    Grid[0].set_yticks(np.arange(0,10), labels=list(np.arange(1,11)), fontsize=6)
    Grid[0].set_ylabel('Depart', fontweight='bold', fontsize=8)

    for cax in Grid.cbar_axes:
        cax.remove()

    cbar = Grid[0].figure.colorbar(heatmap, ax = Grid, fraction=0.2, aspect=50, location='bottom', label='Gaps')
    plt.suptitle('Visualisation of different gaps', fontsize=15, fontweight='bold', y=0.97)
    plt.show()
Trenton McKinney
  • 56,955
  • 33
  • 144
  • 158
Alistair Lucet
  • 125
  • 1
  • 13
  • Check: https://stackoverflow.com/questions/74267842/how-to-save-figure-in-matplotlib-ajusted-to-the-object-size/74269297#74269297 – Joao_PS Jun 02 '23 at 01:17
  • @Joao_PS I've tried the two options (```plt.figure``` and ```set_layout_engine```) but both of them don't solve my issue and I get an error : ```UserWarning: There are no gridspecs with layoutgrids. Possibly did not call parent GridSpec with the "figure" keyword plt.savefig('Test.png', dpi=800, transparent=True)``` – Alistair Lucet Jun 02 '23 at 05:35
  • When I execute your code I get `AttributeError: 'ImageGrid' object has no attribute 'get_figure'`, – gboffi Jun 02 '23 at 07:01
  • @gboffi I'm running my code on Python 3.11.3 with matplotlib 3.7.1 and I don't get any error message and I don't use ```get_figure``` attribute in my code – Alistair Lucet Jun 02 '23 at 10:46

1 Answers1

2

You don't trust Matplotlib capabilities.

enter image description here

To obtain the above figure, I have

  1. left alone the contents of grille.cbar_axes
  2. used grille.cbar_axes to place the colorbar
  3. left the suptitle's position to be decided by Matplotlib
  4. used plt.tight_layout() to have all the spaces left to a minimum
def graphs():
    fig = plt.figure(figsize=(13.5, 6.8), dpi=60) # low dpi to fit the window on my screen
    grille = AxesGrid(fig, 111, nrows_ncols=(1,3),
                      axes_pad=0.2, share_all=False, label_mode='L',
                      cbar_location="bottom", cbar_mode="single")

    Matrices = [np.random.randint(-100,10,(10,10)) for i in range(3)]
    M, m = np.max(Matrices), np.min(Matrices)

    for values, ax in zip(Matrices, grille):

        ax.tick_params(top = True, bottom = False, labeltop = True, labelbottom = False)
        ax.xaxis.set_label_position('top')

        heatmap = ax.imshow(values, vmin=m, vmax=M, cmap='plasma')
        ax.set_xticks(np.arange(0,10), labels=list(np.arange(1,11)), fontsize=6)/
        ax.set_xlabel('Arrival', fontweight='bold', fontsize=8)
        plt.setp(ax.get_xticklabels(), rotation=35, ha="center", rotation_mode=None)

        for l in range(len(values)):
            for c in range(len(values[l])):
                text = ax.text(c, l, values[l,c], ha="center", va="center", color='k', fontsize=6)

        ax.set_title('Gaps', fontweight='bold', fontsize=9)

    grille[0].set_yticks(np.arange(0,10), labels=list(np.arange(1,11)), fontsize=6)
    grille[0].set_ylabel('Depart', fontweight='bold', fontsize=8)

    cbar = plt.colorbar(heatmap, cax=grille.cbar_axes[0], orientation='horizontal', label='Gaps')
    plt.suptitle('Visualisation of different gaps', fontsize=15, fontweight='bold')
    plt.tight_layout()
    plt.show()
graphs()

Addendum

  1. You can change the "thickness" and the spacing of the colorbar using appropriate keyword arguments to AxesGrid; e.g., in the following I've used cbar_size="2%", cbar_pad=0.05
    enter image description here
  2. Re white space, the whole of titles, plots and colorbar when packed has a well defined aspect ratio, additional white space is added vertically or horizontally according to the aspect ratio of the figure — here it is what happens when figsize=(13.5, 5)
    enter image description here
gboffi
  • 22,939
  • 8
  • 54
  • 85
  • It helps with the space in the bottom even if it returns a warning: ```UserWarning: This figure includes Axes that are not compatible with tight_layout, so results might be incorrect. plt.tight_layout()``` but I can't change the width of the color bar with the ```aspect``` parameters – Alistair Lucet Jun 02 '23 at 12:49
  • My code may not be the most effective as I “build” it step by step, adding details one by one – Alistair Lucet Jun 02 '23 at 12:54
  • 1
    It;s just a warning, "results may be incorrect" — but they are correct. – gboffi Jun 02 '23 at 14:12
  • Where should '''cbar_size''' and '''cbar_pad''' be placed as they are not argument of '''plt.colorbar''' – Alistair Lucet Jun 02 '23 at 19:45
  • 1
    @AlistairLucet W.r.t. usage of `cbar_*=...`, please see my recent edit. – gboffi Jun 02 '23 at 20:07