Ticks position in heatmap with categorical data (seaborn)

Viewed 1068

I am trying to plot a confusion matrix of my predictions. My data is multi-class (13 different labels) so I'm using a heatmap.

As you can see below, my heat map looks generally okay but the labels are a bit out of position: y ticks should be a little lower and x ticks should be a bit more to the right. I want to move both axis ticks a bit so they will aligned with the center of each square.

My Confusion Matrix

my code:

sns.set()
my_mask = np.zeros((con_matrix.shape[0], con_matrix.shape[0]), dtype=int)
for i in range(con_matrix.shape[0]):
    for j in range(con_matrix.shape[0]):
        my_mask[i][j] = con_matrix[i][j] == 0 

fig_dims = (10, 10)
plt.subplots(figsize=fig_dims)
ax = sns.heatmap(con_matrix, annot=True, fmt="d", linewidths=.5, cmap="Pastel1", cbar=False, mask=my_mask, vmax=15)
plt.xticks(range(len(party_names)), party_names, rotation=45)
plt.yticks(range(len(party_names)), party_names, rotation='horizontal')
plt.show()

and for reproduction purpose, here are con_matrix and party_names hard-coded:

import numpy as np
from matplotlib import pyplot as plt
import seaborn as sns 

con_matrix = np.array([[55, 0, 0, 0,0, 0, 0,0,0,0,0,0,2], [0,199,0,0,0,0,0,0,0,0,2,0,1],
 [0, 0,52,0,0,0,0,0,0,0,0,0,1],
 [0,0,0,39,0,0,0,0,0,0,0,0,0],
 [0,0,0,0,90,0,0,0,0,0,0,4,3],
 [0,0,0,1,0,35,0,0,0,0,0,0,0],
 [0,0,0,0,5,0,26,0,0,1,0,1,0],
 [0,5,0,0,0,1,0,44,0,0,3,0,1],
 [0,1,0,0,0,0,0,0,52,0,0,0,0],
 [0,1,0,0,2,0,0,0,0,235,0,1,1],
 [1,2,0,0,0,0,0,3,0,0,34,0,3],
 [0,0,0,0,5,0,0,0,0,1,0,40,0],
 [0,0,0,0,0,0,0,0,0,1,0,0,46]])

party_names = ['Blues', 'Browns', 'Greens', 'Greys', 'Khakis', 'Oranges', 'Pinks', 'Purples', 'Reds', 'Turquoises', 'Violets', 'Whites', 'Yellows']

I already tried to work with position argument of different axes, but it did not turn out well. Could not find an exactly answer in this site as well (at least not a solution that works for categorical data).

I'm new in visualization with seaborn, any improvement with explanations would be appreciated (not only for my problem but on my code & visualization as well).

1 Answers

You can shift both the ticklabels by 0.5 offset to have the desired alignment. To do so, I have used NumPy's arange that enables vectorized addition of 0.5 to the whole array.

plt.xticks(np.arange(len(party_names))+0.5, party_names, rotation=45)
plt.yticks(np.arange(len(party_names))+0.5, party_names, rotation='horizontal')

enter image description here

Related