user4599
user4599

Reputation: 127

apply color to the cells based on the value in cell in dataframe

enter image description here

working code

 import pandas as pd
import seaborn as sns
import matplotlib as mpl
import numpy as np
from matplotlib import colors,cm
from matplotlib import pyplot as plt

filename = r'c:\Users\91956\Desktop\time_50.csv'
df = pd.read_csv(filename,index_col=0)
select_col = df.columns[1:]

cmap = mpl.colors.LinearSegmentedColormap.from_list("", ["red","white", "green"])

def background_gradient(s, cmap='PuBu', low=0, high=0):
    s = pd.to_numeric(s, errors='coerce') #<-- here, string will become nan.
    m = s.min() #<---------- here
    M = s.max() #<-----------here
    rng = M - m
    norm = colors.TwoSlopeNorm(vmin=m - (rng * low), vcenter=0., vmax=M + (rng * high))
    normed = norm(s.values)
    c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]
    return ['background-color: %s' % color for color in c]

S = df.style.apply( background_gradient,
                    cmap=cmap,
                    low=0.5,
                    high=0.5,
                    subset= pd.IndexSlice[:, select_col],
                    axis=1
                )

html = S.render()
with open("output.html","w") as fp:
    fp.write(html)

i was getting this error

File "c:\Users\91956\Desktop\asdf.py", line 29, in m=df.min().min(), File "C:\Users\91956\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\generic.py", line 11468, in stat_func return self._reduce( File "C:\Users\91956\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\series.py", line 4248, in _reduce return op(delegate, skipna=skipna, **kwds) File "C:\Users\91956\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\nanops.py", line 129, in f result = alt(values, axis=axis, skipna=skipna, **kwds) File "C:\Users\91956\AppData\Local\Programs\Python\Python39\lib\site-packages\pandas\core\nanops.py", line 873, in reduction result = getattr(values, meth)(axis) File "C:\Users\91956\AppData\Local\Programs\Python\Python39\lib\site-packages\numpy\core_methods.py", line 43, in _amin return umr_minimum(a, axis, None, out, keepdims, initial, where) TypeError: '>=' not supported between instances of 'numpy.ndarray' and 'str'

update 2 did necessary changes. was able to get required output.

enter image description here

Upvotes: 1

Views: 997

Answers (1)

Pygirl
Pygirl

Reputation: 13349

This answer will help and also this answer.

To create sample df:

import pandas as pd
import numpy as np

np.random.seed(24)
df = pd.DataFrame({'A': np.linspace(1, 10, 10)})
df = pd.concat([df, pd.DataFrame(np.random.randn(10, 4), columns=list('BCDE'))],
               axis=1)
df.iloc[3, 3] = np.nan
df.iloc[0, 2] = np.nan

from matplotlib import colors

cmap=LinearSegmentedColormap.from_list('rg',["r","w","g"], N=256) 

def background_gradient(s, m, M, cmap='PuBu', low=0, high=0):
    s = pd.to_numeric(s, errors='coerce') #<-- here, string will become nan.
    print(s)
    rng = M - m
    norm = colors.DivergingNorm(vmin=m - (rng * low), vcenter=0., vmax=M + (rng * high))
    normed = norm(s.values)
    c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]
    return ['background-color: %s' % color for color in c]

x = df.apply(pd.to_numeric, errors='coerce') #<--- here string will be converted to `NaN` so that I can find out the max and min value.
df.style.apply(background_gradient,
               cmap=cmap,
               m=x.min().min(),
               M=x.max().max(),
               low=0.5,
               high=0.5, subset=pd.IndexSlice[:, ['B', 'C']]
              )

enter image description here

Edit:

pass subset=pd.IndexSlice[:, ['B', 'C']] to apply <-- I want to apply colour on B and C column.

df.style.apply(background_gradient,
               cmap=cmap,
               m=df.min().min(),
               M=df.max().max(),
               low=0.5,
               high=0.5, subset=pd.IndexSlice[:, ['B', 'C']]
              )

Edit2:

from matplotlib import colors

cmap=LinearSegmentedColormap.from_list('rg',["r","w","g"], N=256) 

def background_gradient(s, cmap='PuBu', low=0, high=0):
    s = pd.to_numeric(s, errors='coerce')
    m = s.min() #<---------- here
    M = s.max() #<-----------here
    rng = M - m
    norm = colors.DivergingNorm(vmin=m - (rng * low), vcenter=0., vmax=M + (rng * high))
    normed = norm(s.values)
    c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]
    return ['background-color: %s' % color for color in c]

# x = df.apply(pd.to_numeric, errors='coerce')
df.style.apply(background_gradient,
               cmap=cmap,
               low=0.5,
               high=0.5, subset=pd.IndexSlice[:, ['B', 'C', 'D']],  axis=1
              )

Use axis=1 in apply (along column wise comparison for each row)


enter image description here

Upvotes: 2

Related Questions