Smashley
Smashley

Reputation: 57

How to color mask high values on seaborn heat map

I have a heatmap with a few very high values (>5) that I would like to mask red. I have been able to generate my heatmap no problem, but I can't figure out how to mask the high values.

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

 
from openpyxl import load_workbook

wb = load_workbook(filename='Lake Data.xlsx')

ws = wb['PC RFU']

data_rows = []
for row in ws['B77':'DL104']:
    data_cols  = []
    for cell in row:
        data_cols.append(cell.value)
    data_rows.append(data_cols)

df = pd.DataFrame(data_rows)
print(df)
df.columns = df.iloc[0]
df = df.drop([0])

cols = df.select_dtypes(exclude=['float']).columns
df[cols] = df[cols].apply(pd.to_numeric, downcast='float', errors='coerce')

print(df)
print(df.columns)
print(df.info())

f, ax = plt.subplots(figsize=(18, 6))
f.suptitle('Site 03 PC/Chl', fontsize=16)

sns.heatmap(df.drop(['Depth (ft)'], axis='columns'), linewidths=0, ax=ax, cmap=color, robust='true', vmax=5) #,vmin=0,vmax=14, center=4

ax.set_yticklabels(ax.get_yticklabels(), rotation=0)
ax.set_xticklabels(ax.get_xticklabels(), rotation=90)
plt.xlabel('Date')
plt.ylabel('Depth (Ft.)')
plt.show()

enter image description here

The bright yellow squares on the right are actually between 5 and 15, and for those atypical high values >5 I'd like the squares to appear red. I can't seem to figure out how to use the mask feature to do this.

Bonus if someone can also tell me how to get rid of the "00:00:00" in the date axis!

Upvotes: 1

Views: 1653

Answers (1)

JohanC
JohanC

Reputation: 80339

You can use a custom color map, and set its "over" color to red. That way, all values larger than vmax will be colored red.

To restrict the x tick labels to their first 10 characters, you can use t.get_text()[:10].

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

df = pd.DataFrame(np.random.randn(20, 100).cumsum(axis=0),
                  columns=pd.date_range('20210101', freq='D', periods=100))

fig, ax = plt.subplots(figsize=(18, 6))
fig.suptitle('Site 03 PC/Chl', fontsize=16)

my_cmap = plt.get_cmap('viridis').copy()
my_cmap.set_over('red')
sns.heatmap(df, linewidths=0, ax=ax, cmap=my_cmap, robust='true', vmax=5)

ax.set_yticklabels(ax.get_yticklabels(), rotation=0)
ax.set_xticklabels([t.get_text()[:10] for t in ax.get_xticklabels()], rotation=90)
plt.xlabel('Date')
plt.ylabel('Depth (Ft.)')
plt.tight_layout()
plt.show()

using an "over" color

Additionally, you might add extra parameters to the colorbar, e.g. sns.heatmap(..., cbar_kws={'pad': 0.02, 'extend': 'max', 'extendrect': True}):

  • 'pad': 0.02 to reduce the spacing between plot and colorbar
  • 'extend': 'max' to show the "over" color in the colorbar
  • 'extendrect': True to show the "over" color as a rectangle (default is a triangle)

PS: You might try pd.read_excel() to read the file directly and experiment with its parameters, in order to create the dataframe without manipulations.

Upvotes: 3

Related Questions