Search code examples
pythonsubplotcolorbarimshow

One colorbar for two imshows


i have the following code and somehow i can not place the colorbar in such a place that it is not overlapping with the imshow itself and if I place it further outside it is cutted off :( I tried already a lot of things, but nothing worked for this problem. If the colorbar is not horizontal that would work for me, too, but then the label of the axis need to be perpendicular too.

HELP

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


vegetables = [ "One magnet", "Two magnets","washer",
              "ST37 - 1", "ST37 - 2", "ST37 - 3", "RVS"]



farmers0 = ["1 cm/s", "1.25 cm/s"]



mask0 = np.array([[False, False, False, False, False, False, False],
                    [False, False, False, True, True, True, True]])

harvest1 = np.array([[ 1.9, 1.6,1.1,1.2,1.1,0.5,0.7],
                    [ 1.6, 0.8,0.9, 0,0,0,0]])

harvest1 = np.ma.array(harvest1, mask=mask0)

harvest2 = np.array([[ 0.9, 1.0,0.7,1.0,1.1,0.4,0.6],
                    [ 0.9, 0.8,0.8, 0,0,0,0]])
harvest2 = np.ma.array(harvest2, mask=mask0)




fig, ax = plt.subplots(2, sharex=True, sharey=False)



im0 = ax[0].imshow(harvest1, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65)

# We want to show all ticks...
ax[0].set_xticks(np.arange(len(vegetables)))
ax[0].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[0].set_xticklabels(vegetables)
ax[0].set_yticklabels(farmers0)


# Rotate the tick labels and set their alignment.
plt.setp(ax[0].get_xticklabels(), rotation=45, ha="right",
         rotation_mode="anchor")



for i in range(len(farmers0)):
    for j in range(len(vegetables)):
        text = ax[0].text(j, i, harvest1[i, j],
                       ha="center", va="center", color="k")
    

im0 = ax[1].imshow(harvest2, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65)

# We want to show all ticks...
ax[1].set_xticks(np.arange(len(vegetables)))
ax[1].set_yticks(np.arange(len(farmers0)))
# ... and label them with the respective list entries
ax[1].set_xticklabels(vegetables)
ax[1].set_yticklabels(farmers0)


# Rotate the tick labels and set their alignment.
plt.setp(ax[1].get_xticklabels(), rotation=45, ha="right",
         rotation_mode="anchor")



for i in range(len(farmers0)):
    for j in range(len(vegetables)):
        text = ax[1].text(j, i, harvest2[i, j],
                       ha="center", va="center", color="k")
 
#fig.colorbar(im0, ax=ax.ravel().tolist(), orientation = 'horizontal')



#plt.gcf().subplots_adjust(top=1.5)

fig.tight_layout()

cbaxes = fig.add_axes([0.15,0.9,0.82,0.05]) #links, hight
#cax = divider.append.axes("bottom", size= "5%", pad = 0.05)
bar2 = plt.colorbar(im0, cax = cbaxes , orientation = 'horizontal')

bar2.ax.set_title('90 % confidence interval of $d$')



plt.show()

Solution

  • here's a version that uses GridSpec to get more control over the axis-grid (e.g. so you can adjust the spacing between colorbar and axes etc.)

    also note that i use aspect='auto' in the ax.imshow calls to allow non-square pixels!

    import numpy as np
    import matplotlib
    import matplotlib.pyplot as plt
    
    from matplotlib.gridspec import GridSpec, GridSpecFromSubplotSpec
    
    vegetables = [ "One magnet", "Two magnets","washer",
                  "ST37 - 1", "ST37 - 2", "ST37 - 3", "RVS"]
    
    
    
    farmers0 = ["1 cm/s", "1.25 cm/s"]
    
    
    
    mask0 = np.array([[False, False, False, False, False, False, False],
                        [False, False, False, True, True, True, True]])
    
    harvest1 = np.array([[ 1.9, 1.6,1.1,1.2,1.1,0.5,0.7],
                        [ 1.6, 0.8,0.9, 0,0,0,0]])
    
    harvest1 = np.ma.array(harvest1, mask=mask0)
    
    harvest2 = np.array([[ 0.9, 1.0,0.7,1.0,1.1,0.4,0.6],
                        [ 0.9, 0.8,0.8, 0,0,0,0]])
    harvest2 = np.ma.array(harvest2, mask=mask0)
    
    
    # -----------------------------------------------
    # manually create an axes to have full control over spacing etc.
    gs = GridSpec(2, 1, 
                  height_ratios=(.5, 9.5))
    gs_ax = GridSpecFromSubplotSpec(2, 1, gs[1], 
                                    hspace=.5)
    
    fig = plt.figure(figsize=(7, 7))
    ax = []
    ax.append(fig.add_subplot(gs_ax[0]))
    ax.append(fig.add_subplot(gs_ax[1]))
    
    cbaxes = fig.add_subplot(gs[0])
    
    # manually ensure that x- and y- axes are shared
    ax[0].get_shared_x_axes().join(ax[1])
    ax[0].get_shared_y_axes().join(ax[1])
    # -----------------------------------------------
    
    im0 = ax[0].imshow(harvest1, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65,
                       aspect="auto")
    
    # We want to show all ticks...
    ax[0].set_xticks(np.arange(len(vegetables)))
    ax[0].set_yticks(np.arange(len(farmers0)))
    # ... and label them with the respective list entries
    ax[0].set_xticklabels(vegetables)
    ax[0].set_yticklabels(farmers0)
    
    
    # Rotate the tick labels and set their alignment.
    plt.setp(ax[0].get_xticklabels(), rotation=45, ha="right",
             rotation_mode="anchor")
    
    
    
    for i in range(len(farmers0)):
        for j in range(len(vegetables)):
            text = ax[0].text(j, i, harvest1[i, j],
                           ha="center", va="center", color="k")
        
    
    im0 = ax[1].imshow(harvest2, cmap='RdYlGn_r', vmin = 0.5, vmax = 1.65,
                       aspect="auto")
    
    # We want to show all ticks...
    ax[1].set_xticks(np.arange(len(vegetables)))
    ax[1].set_yticks(np.arange(len(farmers0)))
    # ... and label them with the respective list entries
    ax[1].set_xticklabels(vegetables)
    ax[1].set_yticklabels(farmers0)
    
    
    # Rotate the tick labels and set their alignment.
    plt.setp(ax[1].get_xticklabels(), rotation=45, ha="right",
             rotation_mode="anchor")
    
    
    
    for i in range(len(farmers0)):
        for j in range(len(vegetables)):
            text = ax[1].text(j, i, harvest2[i, j],
                           ha="center", va="center", color="k")
     
    
    #cax = divider.append.axes("bottom", size= "5%", pad = 0.05)
    bar2 = plt.colorbar(im0, cax = cbaxes , orientation = 'horizontal')
    
    bar2.ax.set_title('90 % confidence interval of $d$')
    
    fig.tight_layout()
    
    plt.show()
    

    enter image description here