pythonmatplotlibsubplotcolorbarmatplotlib-gridspec

How to place a single colorbar for two gridspec subplots


I am trying to plot 6 plots in the form of a grid using gridspec. I want one color bar placed at the bottom between the 2nd and 3rd columns.

My code is as follows, but it generates 6 colorbars. How can I change this code so that it places one colorbar at the bottom between the two columns? enter image description here

import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes


plt.figure(figsize=(8, 6))
gs = gridspec.GridSpec(2, 3)
gs.update(wspace= 1)

cmaps = ['RdBu_r', 'viridis', 'viridis']

for i in range(2):
  for j in range(3):
      ax = plt.subplot(gs[i, j])
      image = ax.pcolormesh(np.random.random((20, 20)) * (j + 1),
                            cmap=cmaps[j])
      #image = ax.imshow(im)
      axins = inset_axes(ax, 
               width="10%",  
               height="100%",  
               loc='lower left',
               bbox_to_anchor=(1.05, 0.0, 1, 1),
               bbox_transform=ax.transAxes,
               borderpad=0
               )
               
      cb = plt.colorbar(image, cax=axins)

I want the color bar placed horizontally at the bottom spanning columns 2 and 3 (I marked in red where I want it to be placed).


Solution

  • Matplotlib is smart enough to give you the option to create a colorbar for multiple axis at once using the ax argument:

    import numpy as np
    import matplotlib.gridspec as gridspec
    import matplotlib.pyplot as plt
    
    plt.figure(figsize=(8, 6))
    gs = gridspec.GridSpec(2, 3)
    gs.update(wspace= 1)
    
    cmaps = ['RdBu_r', 'viridis', 'viridis']
    
    axs = [[],[]]
    for i in range(2):
      for j in range(3):
          ax = plt.subplot(gs[i, j])
          axs[i].append(ax)
          image = ax.pcolormesh(
              np.random.random((20, 20)) * (j + 1),
              cmap=cmaps[j])
    
    # converting to numpy array for easier slicing
    axs = np.array(axs)
    
    cb = plt.colorbar(
        image,
        ax=axs[:,1:], # select all axis from second column
        orientation='horizontal')
    

    Colorbar for multiple axis using ax

    The colorbar will take a part of the axis and the first column will not be aligned at the bottom.

    If this bothers you, define the colorbar axis manually with an extra row in your gridspec. To control the height of colorbar, modify the grispec height ratios (height_ratios=[1,1,.1], more in gridspec's documentation). My try:

    import numpy as np
    import matplotlib.gridspec as gridspec
    import matplotlib.pyplot as plt
    
    plt.figure(figsize=(8, 6))
    
    gs = gridspec.GridSpec(
        3, 3,
        height_ratios=[1,1,.1]) 
    gs.update(wspace= 1)
    
    cmaps = ['RdBu_r', 'viridis', 'viridis']
    
    axs = [[],[]]
    for i in range(2):
      for j in range(3):
          ax = plt.subplot(gs[i, j])
          axs[i].append(ax)
          image = ax.pcolormesh(
              np.random.random((20, 20)) * (j + 1),
              cmap=cmaps[j])
    
    # ax is not necessary if cax is given
    cb = plt.colorbar(
        image,
        cax=plt.subplot(gs[-1, 1:]),
        orientation='horizontal')
    

    Colorbar for multiple axis using cax