How to add rectangle patches in Python Heatmap?

Viewed 1028

enter image description here

Below code gives me the heatmap output. but I want to add rectangle patches to highlight values in the range of 0.4 to 0.99 and -0.4 to -0.99

plt.figure(figsize=(15,10))
mask = np.triu(np.ones_like(corr, dtype=np.bool)) 
sns.heatmap(corr,annot=True,fmt=".2f", mask=mask,cmap="YlGnBu");

2 Answers

The heatmap data for the categorical variables was taken from Kaggle's home price data. To add a rectangle, add a rectangle to add_patch(). The coordinates are based on the lower left corner, so specify the x and y of each in tuples, and specify the width and height. We also specify not to fill it.

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig, ax = plt.subplots(figsize=(18,18))
df_house = pd.read_csv('./data/house_prices_train.csv', index_col=0)
df_house_corr = df_house.corr()
mask = np.triu(np.ones_like(df_house_corr, dtype=np.bool)) 
sns.heatmap(df_house_corr, annot=True, fmt=".2f", mask=mask, cmap="YlGnBu")

ax.add_patch(
     patches.Rectangle(
         (5, 6),
         1.0,
         35.0,
         edgecolor='red',
         fill=False,
         lw=2
     ) )

plt.show()

enter image description here

Ok so without the data I made the solution with the values of a uniform distribution. Copy-paste your data in the script and it should work as long as they are of NumPy array-like type.

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
import seaborn as sns

fig, ax = plt.subplots(figsize=(15, 10))

data_len = 17
uniform_data = np.random.rand(data_len, data_len)
# np.bool is deprecated in Numpy 1.20
mask = np.triu(np.ones_like(uniform_data, dtype=bool))
heatmap = sns.heatmap(uniform_data, annot=True, fmt='.2f', mask=mask, cmap='YlGnBu', ax=ax)

indices_tuple = np.tril_indices(n=data_len, k=-1)
# first array of indices_tuple: indices on column
# second array of indices_tuple: indices on lines
for col_index, line_index in zip(indices_tuple[0], indices_tuple[1]):
    if (np.abs(uniform_data[line_index, col_index]) <= 0.99) and (np.abs(uniform_data[line_index, col_index]) >= 0.4):
        rect = patches.Rectangle((line_index, col_index), 1, 1, fill=True, facecolor='red', alpha=0.5)
        ax.add_patch(rect)
plt.show()

The idea is to get the indices of all the values of the lower triangle to prevent looping through unnecessary values. The latter values are inspected and if the condition is met, a rectangle is drawn at its position.

You get the following result: description

If I correctly understood your problem, this script should do the trick.

Related