5

Unsure if it is possible to leverage matplotlib's DivergingNorm for color maps under the framework of pandas Styler objects. As an example:

import pandas as pd
import matplotlib.cm

# retrieve red-yellow-green diverging color map
cmap = matplotlib.cm.get_cmap('RdYlGn')

# create sample pd.DataFrame
ix = pd.date_range(start=pd.Timestamp(2020, 1, 1), periods=4)
df = pd.DataFrame(index=ix, columns=['D/D CHANGE'], data=[-1, 0, 2, 5])

df.style.background_gradient(cmap=cmap)

enter image description here

Ideally only negative (positive) values would appear red (green).

Henry Ecker
  • 34,399
  • 18
  • 41
  • 57
Rations
  • 177
  • 1
  • 8

1 Answers1

7

It doesn't look like there is an option to pass a custom normalization to background_gradient (maybe could be a feature request to post on pandas github). But you can use a custom function to get the desired result:

def background_with_norm(s):
    cmap = matplotlib.cm.get_cmap('RdYlGn')
    norm = matplotlib.colors.DivergingNorm(vmin=s.values.min(), vcenter=0, vmax=s.values.max())
    return ['background-color: {:s}'.format(matplotlib.colors.to_hex(c.flatten())) for c in cmap(norm(s.values))]

# create sample pd.DataFrame
ix = pd.date_range(start=pd.Timestamp(2020, 1, 1), periods=4)
df = pd.DataFrame(index=ix, columns=['D/D CHANGE'], data=[-1, 0, 2, 5])

df.style.apply(background_with_norm)

enter image description here

Diziet Asahi
  • 38,379
  • 7
  • 60
  • 75
  • Works great. I put added a condition to ensure that s.values.min() < 0 < s.values.max(), in case the series is all negative or all positive. – Rations Mar 12 '20 at 19:43
  • How can I do this with multiple columns, applying the function to each column individually? – abrer Apr 24 '22 at 18:11