Creating a 2 colour heatmap with Python

Question:

I have numerous sets of seasonal data that I am looking to show in a heatmap format. I am not worried about the magnitude of the values in the dataset but more the overall direction and any patterns that i can look at in more detail later. To do this I want to create a heatmap that only shows 2 colours (red for below zero and green for zero and above).

I can create a normal heatmap with seaborn but the normal colour maps do not have only 2 colours and I am not able to create one myself. Even if I could I am unable to set the parameters to reflect the criteria of below zero = red and zero+ = green.

I managed to create this simply by styling the dataframe but I was unable to export it as a .png because the table_criteria=’matplotlib’ option removes the formatting.

Below is an example of what I would like to create made from random data, could someone help or point me in the direction of a helpful Stackoverflow answer?

I have also included the code I used to style and export the dataframe.

Desired output – this is created with random data in an Excel spreadsheet

#Code to create a regular heatmap - can this be easily amended?

df_hm = pd.read_csv(filename+h)
pivot = df_hm.pivot_table(index='Year', columns='Month', values='delta', aggfunc='sum')      
fig, ax = plt.subplots(figsize=(10,5))
ax.set_title('M1 '+h[:-7])
sns.heatmap(pivot, annot=True, fmt='.2f', cmap='RdYlGn')
plt.savefig(chartpath+h[:-7]+" M1.png", bbox_inches='tight')
plt.close()

#code used to export dataframe that loses format in the .png

import matplotlib.pyplot as plt
import dataframe_image as dfi
#pivot is the dateframe name
pivot = pd.DataFrame(np.random.randint(-100,100,size= (5, 12)),columns=list ('ABCDEFGHIJKL'))
styles = [dict(selector="caption", props=[("font-size", "120%"),("font-weight", "bold")])]
    pivot = pivot.style.format(precision=2).highlight_between(left=-100000, right=-0.01, props='color:white;background-color:red').highlight_between(left=0, right= 100000, props='color:white;background-color:green').set_caption(title).set_table_styles(styles)
dfi.export(pivot, root+'testhm.png', table_conversion='matplotlib',chrome_path=None)

Asked By: Rich

||

Answers:

Welcome to SO!

To achieve what you need, you just need to pass delta through the sign function, here’s an example code:

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

arr = np.random.randn(25,25)

sns.heatmap(np.sign(arr))

Output Heatmap

Which results in a binary heatmap, albeit one with a quite ugly colormap, still, you can fiddle around with Seaborn’s colormaps in order to make it look like excel.

Answered By: Neervana

You can manually set cmap property to list of colors and if you want to annotate you can do it and it will show same value as it’s not converted to -1 or 1.

import numpy as np
import seaborn as sns

arr = np.random.randn(10,10)
sns.heatmap(arr,cmap=["grey",'green'],annot=True,center=0) 
# center will make it dividing point

Output:
heatmap

PS. If you don’t want color-bar you can pass cbar=False in `sns.heatmap)

Answered By: GodWin
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.