Reputation: 4162
I have a code to change the cell background colour if the Rising
is False. I want to change the Cell Colour to Green if the value in the Index
is Nifty 50
.
So If any rows is from Nifty 50
but Rising
is False, then the Nifty 50
cell should be in Green background of that Only cell and all of the other cells should be in Red.
This is what I want the Dataframe to look like: Whole Row is Red if
Rising
is False or 0
. Color of Index
is changed based on whether it is from Nifty-50/100/200
And the code for changing color is as follows:
def highlight_falling(s, column:str):
'''
Highlight The rows where average is falling
args:
s: Series
column: Column name(s)
'''
is_max = pd.Series(data=False, index=s.index)
is_max[column] = s.loc[column] == True
return ['' if is_max.any() else 'background-color: #f7a8a8' for v in is_max]
picked.style.apply(highlight_falling, column=['Rising'], axis=1) # picked is the DF
Here I want to give the Index of 50,100,200,500 cell as [Green,Blue,Magenta. White]
(just tan example)
Upvotes: 0
Views: 1531
Reputation: 35686
We can use use Series.map
to associate the values in the column with the new color styles. We will then apply the Index
column styles after the row styles so as to override the previously placed red colour:
def highlight_falling(f: pd.DataFrame, column: str):
# Create an Empty DataFrame
f_styles = pd.DataFrame('', index=f.index, columns=f.columns)
# Apply Styles based on column. (Set red where not Truthy)
f_styles.loc[~(f[column].astype(bool)), :] = 'background-color: #f7a8a8'
return f_styles
def highlight_nifty(s: pd.Series):
return 'background-color: ' + s.map({
'Nifty 50': 'green',
'Nifty 100': 'blue',
'Nifty 200': '#888888'
}) # Map to colour codes
# Save Styler To Re-use (can also Chain)
styler = picked.style
# Apply Row Colour (Do not pass column as List[str] use str!!)
styler.apply(highlight_falling, column='Rising', axis=None)
# Apply Index Column Colours
styler.apply(highlight_nifty, subset='Index')
The mapping dictionary could also be created with dict
and zip
if wanted to specify a list of colors can use unique
to get all unique values from the Index column, then natsorted
can be used to order them (safe alphanumeric ordering):
from natsort import natsorted
from typing import List
def highlight_falling(f: pd.DataFrame, column: str):
# Create an Empty DataFrame
f_styles = pd.DataFrame('', index=f.index, columns=f.columns)
# Apply Styles based on column. (Set red where not Truthy)
f_styles.loc[~(f[column].astype(bool)), :] = 'background-color: #f7a8a8'
return f_styles
def highlight_nifty(s: pd.Series, colours: List[str]):
return 'background-color: ' + s.map(
# Build Colour Map Dynamically based on unique values from column
dict(zip(natsorted(s.unique()), colours))
) # Map to colour codes
# Save Styler To Re-use (can also Chain)
styler = picked.style
# Apply Row Colour (Do not pass column as List[str] use str!!)
styler.apply(highlight_falling, column='Rising', axis=None)
# Apply Index Column Colours
styler.apply(highlight_nifty, subset='Index',
colours=['green', 'blue', '#888888'])
Upvotes: 1