Home > other >  How to align the heatmap y-ticks in the center on the secondary axis
How to align the heatmap y-ticks in the center on the secondary axis

Time:09-20

I have a data frame like this:

l1 = ['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B']
l2 = ['Name-1','Name-2','Name-3','Name-4','Name-5','Name-6','Name-7','Name-8','Name-9','Name-10','Name-11','Name-12','Name-13','Name-14','Name-15','Name-16','Name-17','Name-18','Name-19','Name-20']
v1 = [1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1]
v2 = [0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,0,0,1,1]
v3 = [1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0]
v4 = [0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1]
v5 = [1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1]
v6 = [1,1,0,0,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,1]
v7 = [0,0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,1,0,1]
v8 = [0,1,0,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1]
v9 = [1,1,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1]
v10 =[1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,0,1,1,0,1]
d = {'variable': l1, 'value': l2,'ID1': v1,'ID2': v2,'ID3': v3,'ID4': v4,'ID5': v5,'ID6': v6,'ID7': v7,'ID8': v8,'ID9': v9,'ID10': v10} 
df = pd.DataFrame(d)
df = df.set_index(['variable','value'])

sum_list = df.sum(axis=0)

and I created a heatmap with Y-tick labels on the left and right. which looks like this:

sns.set(rc={'figure.figsize': (10,10),'xtick.labelsize': 12,'ytick.labelsize': 12, 'axes.labelcolor': 'black',
           'ytick.left': True, 'ytick.right': True,'axes.grid': False,})
heat_map = sns.heatmap(df.reset_index(level='variable', col_level=0,drop=True),square=False,yticklabels=True,xticklabels=False,cmap=['#FFFFFF','#ff0303'],vmin=0,vmax=1,cbar=False,linewidths=1,linecolor='black', annot_kws={"fontsize":3})
heat_map.set_yticklabels(labels=heat_map.get_yticklabels(),weight='bold',color='black')
heat_map.set(xlabel=None,ylabel=None)
sec_axis=heat_map.twinx()
sec_axis.set_yticks(heat_map.get_yticks())
sec_axis.set_yticklabels(df.sum(axis=1).values[::-1], weight='bold', color='black', fontsize=12) ## Add tick labels which will be the sum
sec_axis.grid(False)

By adding second y-ticklabels(right side), my edges along 4 sides disappeared and yticks on the right side are not aligned in the center. I want to:

  1. Display the heatmap along with edges visible
  2. Center-align the yticks on the secondary y-axis

This is how my heatmap looks: IMAGE

CodePudding user response:

You can add a secondary axis using tiwnx(). Get the sum of values of each row using df.sum(axis=1).values[::-1] so that the sum is set in the right order and then use set_yticklabels() show the same. Add the below code to your existing code.

sec_axis=heat_map.twinx() ##sec_axis in the secondary axis (y axis on right)
sec_axis.set_yticks(heat_map.get_yticks()) ## Use same ticks as the primary axis
sec_axis.set_yticklabels(df.sum(axis=1).values[::-1], weight='bold', color='black', fontsize=12) ## Add tick labels which will be the sum
sec_axis.grid(False) ## Remove any grid lines for secondary axis if present

NEW REQ

I have updated the code to adjust the secondary y-ticks. Looks like the edge lines were not present in your original plot or request. Anyway, added the code for that as well.

  • To adjust the y-ticks, use get_ylim() and adjust it so that this adjusts to the primary y-ticks and use set_major_locator() to set the secondary y-axis()
  • splines should have worked, but seems like this is not showing. Used axhline and and axvline in its place.
l1 = ['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B','B','B','B','B','B']
l2 = ['Name-1','Name-2','Name-3','Name-4','Name-5','Name-6','Name-7','Name-8','Name-9','Name-10','Name-11','Name-12','Name-13','Name-14','Name-15','Name-16','Name-17','Name-18','Name-19','Name-20']
v1 = [1,1,1,1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1,1]
v2 = [0,0,0,1,1,1,0,0,1,1,0,0,0,1,1,1,0,0,1,1]
v3 = [1,0,1,1,1,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0]
v4 = [0,0,0,0,1,1,1,0,0,1,0,0,0,0,1,1,1,0,0,1]
v5 = [1,0,1,0,1,0,1,0,1,1,1,0,1,0,1,0,1,0,1,1]
v6 = [1,1,0,0,1,1,0,1,0,1,1,1,0,0,1,1,0,1,0,1]
v7 = [0,0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,1,0,1]
v8 = [0,1,0,1,1,1,1,0,1,1,0,1,0,1,1,1,1,0,1,1]
v9 = [1,1,0,1,1,1,0,0,0,1,1,1,0,1,1,1,0,0,0,1]
v10 =[1,1,1,0,0,0,1,1,0,1,1,1,1,0,0,0,1,1,0,1]
d = {'variable': l1, 'value': l2,'ID1': v1,'ID2': v2,'ID3': v3,'ID4': v4,'ID5': v5,'ID6': v6,'ID7': v7,'ID8': v8,'ID9': v9,'ID10': v10} 
df = pd.DataFrame(d)
df = df.set_index(['variable','value'])
sum_list = df.sum(axis=0)
sns.set(rc={'figure.figsize': (10,10),'xtick.labelsize': 12, 'ytick.labelsize': 12, 'axes.labelcolor': 'black', 'ytick.left': True, 'ytick.right': True})

heat_map = sns.heatmap(df.reset_index(level='variable', col_level=0, drop=True),square=False,yticklabels=True, xticklabels=False,cmap=['#FFFFFF','#ff0303'], vmin=0,vmax=1,cbar=False,linewidths=1, linecolor='black', annot_kws={"fontsize":3})
heat_map.set_yticklabels(labels=heat_map.get_yticklabels(),weight='bold',color='black')

sec_axis=heat_map.twinx()

import matplotlib.ticker
l = heat_map.get_ylim()
l2 = sec_axis.get_ylim()
f = lambda x : l2[0] (x-l[0])/(l[1]-l[0])*(l2[1]-l2[0])
ticks = f(heat_map.get_yticks())
sec_axis.yaxis.set_major_locator(matplotlib.ticker.FixedLocator(ticks))

sec_axis.set_yticklabels(df.sum(axis=1).values, ha="center", weight='bold', color='black', fontsize=12, va="center")
sec_axis.grid(False)

heat_map.axhline(y = 0, color = 'k', linewidth = 5)
heat_map.axhline(y = 20, color = 'k', linewidth = 5)
heat_map.axvline(x = 0, color = 'k', linewidth = 5)
heat_map.axvline(x = 20, color = 'k', linewidth = 5)

enter image description here

  • Related