0

I have divided a pandas dataframe in several subplots, as it is described in the following code. Every subplot has a specific colorbar. I want to make a common colorbar for all the subplots. The dataframe comes directly from an exel csv file.

Table_1_pos=df_pos.iloc[0:4,0:13]
Table_2_pos=df_pos.iloc[4:8,0:13]
Table_3_pos=df_pos.iloc[8:12,0:13]        
Table_4_pos=df_pos.iloc[12:16,0:13]        
[![enter image description here][1]][1]fig, axs = plt.subplots(nrows=4, gridspec_kw=dict(width_ratios=[4]),figsize=(15,8))  

ax1=sns.heatmap(Table_1_neg, annot=True, yticklabels=True, xticklabels=False, cbar=True, ax=axs[0], linewidths=1)
ax1.set_yticklabels(ax1.get_yticklabels(), rotation=0)
ax1.tick_params(right=True, left=False, labelright=True, labelleft=False)
bottom_1, top_1 = ax1.get_ylim()
ax1.set_ylim(bottom_1 + 0.5, top_1 - 0.5)
ax1.set_ylabel('Table 4')
ax1.set_ylabel(ax1.get_ylabel(),labelpad=20, rotation=0)        


ax2=sns.heatmap(Table_2_neg, annot=True, yticklabels=True, xticklabels=False, cbar=True, ax=axs[1], linewidths=1)
ax2.set_yticklabels(ax2.get_yticklabels(), rotation=0)
ax2.tick_params(right=True, left=False, labelright=True, labelleft=False)
bottom_2, top_2 = ax2.get_ylim()
ax2.set_ylim(bottom_2 + 0.5, top_2 - 0.5)
ax2.set_ylabel('Table 3')
ax2.set_ylabel(ax2.get_ylabel(),labelpad=20, rotation=0)         

ax3=sns.heatmap(Table_3_neg, annot=True, yticklabels=True, xticklabels=False, cbar=True, ax=axs[2], linewidths=1)
ax3.set_yticklabels(ax3.get_yticklabels(), rotation=0)
ax3.tick_params(right=True, left=False, labelright=True, labelleft=False)
bottom_3, top_3 = ax3.get_ylim()
ax3.set_ylim(bottom_3 + 0.5, top_3 - 0.5)
ax3.set_ylabel('Table 2')
ax3.set_ylabel(ax3.get_ylabel(),labelpad=20, rotation=0) 

ax4=sns.heatmap(Table_4_neg, annot=True, yticklabels=True, xticklabels=True, cbar=True, ax=axs[3], linewidths=1)
ax4.set_yticklabels(ax4.get_yticklabels(), rotation=0)
ax4.tick_params(right=True, left=False, labelright=True, labelleft=False)
bottom_4, top_4 = ax4.get_ylim()
ax4.set_ylim(bottom_1 + 0.5, top_1 - 0.5)        
ax4.set_ylabel('Table 1')
ax4.set_ylabel(ax4.get_ylabel(),labelpad=20, rotation=0) 


cbaxes = fig.add_axes([0.95, 0.1, 0.01, 0.8])     
mappable = axs.get_children()[0]         
plt.colorbar(mappable, ax = [ax1,ax2,ax3,ax4],orientation = 'vertical',cax = cbaxes)

plt.title("Tilt = {tilt}    -     WindDir = {winddir} (neg)  -   Cpnet,comparison".format(tilt=x, winddir=y),horizontalalignment='right',x=-30,y=1, verticalalignment='top')

out_fp_neg_1 = os.path.join(image_dirn, outpattern_neg.format(tilt=x, dir=y))

Subplots with multiple colorbars

pantelis
  • 83
  • 6

1 Answers1

1

If all your subplots use the same range of values, you can use the solution presented by Joe Kington.

However, from the image, it seems that all subplots do not have the same range. Hopefully, seaborn allow you to define your heatmap minimum and maximum, as well as the axes on which to draw the colorbar.

Here is a working example:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

def main():
    df_pos = pd.DataFrame(
        np.random.random((16,13)) * 2 - 1
    )
    vmin = df_pos.min().min()
    vmax = df_pos.max().max()

    fig, axes = plt.subplots(nrows=4, ncols=1, figsize=(15,8))
    fig.subplots_adjust(right=0.8)
    cbar_ax = fig.add_axes([0.85, 0.15, 0.05, 0.7])
    for i, ax in enumerate(axes.flat):
        sns.heatmap(
            data=df_pos.iloc[4*i:4*(i+1), 0:13], ax=ax, vmin=vmin, vmax=vmax, cbar_ax=cbar_ax,
            xticklabels=False, yticklabels=False, annot=True, linewidths=1)

    plt.show()


if __name__ == '__main__':
    main()

enter image description here

AlexisBRENON
  • 2,921
  • 2
  • 18
  • 30
  • Hi Alexis, the code you proposed its ideal for my case, but unfortunately i cannot use it, since it is not possible to convert a 13*16 dataframe in a numpy array. I did try a lot of times, but always there was an error – pantelis Dec 20 '19 at 14:10
  • @pantelis I don't see any problem while using a DataFrame. I updated with data coming from a dataframe instead of a numpy array. – AlexisBRENON Dec 20 '19 at 14:48
  • Thank you very much – pantelis Dec 20 '19 at 22:31