Let's say I have a DataFrame that looks like this:
df= pd.DataFrame({'A': [1,-2,0,-1,17],
'B': [11,-23,1,-3,132],
'C': [121,2029,-243,17,-45]}
)
I use a jupyter notebook and want to colour with df.style
the values in each column only if they exceed a value X, where X=1.5*median(column). So, I would like to have something like this:
Preferably, I would like to have some gradient (df.style.background_gradient
) to the colouring of the values, e.g. in column A
the entry 17
to be darker than 1
, because 17 is further away from the median of the column. But the gradient is optional.
How can I do this?
CodePudding user response:
This answer uses pandas 1.4.2, the Styler can function differently depending on version.
The simple case is fairly straightforward. Create a function which accepts a Series as input and then use
Simple support for separate styles for values > 1.5 * median and less than by configuring the true_color
and false_color
values. Naturally, more functionality can be added depending on specific need.
The gradient piece is a bit more involved. We can use
Note: this approach considers all values when normalising so the gradient will be affected by all values in the column.
In case the more general case is needed, an unconditional gradient centered on the median could be built with (the rest is the same as the complete example above):
def centered_gradient(
s: pd.Series, cmap: Colormap, false_css: str = ''
) -> List[str]:
# Find center point
center = 1.5 * s.median()
# Create normaliser centered on median
norm = CenteredNorm(vcenter=center)
# s = s.where(s > center, center)
return [
f'background-color: {rgb2hex(rgba)}' for rgba in cmap(norm(s))
]