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))
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()