Parenthesis in negative numbers on Pandas Styler object

74 views Asked by At

So I got a 3x3 dataframe that looks like this:

import pandas as pd
df = pd.DataFrame([[-232.3,43.1,"hre"],[-245.7,-943.7,"jtr"],[956.3,435.2,"fgjh"]], columns=list("ABC"))

And I'm styling it using:

df_stl = df.style.background_color(axis = None, subset = ["A", "B"], cmap = 'autumn')

I wanna be able to format the final dataframe values (on the Styler object created after all these methods) with parenthesis only on negative number, without losing the background colors.

So I want something like:

A B C
$(232.3) 43.1 "hre"
$(245.7) $(943.7) "jtr"
956.3 435.2 "fgjh"

I tried to add a .map(parent) after .background_color(), where 'parent' is something like this:

def parent(x):
    if(type(x) == float):
        if(x>=0):
            a - f"${x:.,0f}"
        else:
            a = f"$({abs(x):.,0f})"
       else:
        a = x
    return a

So, I tried this:

df_stl = df.style.background_color(axis = None, subset = ["A", "B"], cmap = 'autumn').map(parent)

But it returns a

'ValueError': Styles supplied as string must follow CSS rule formats, for exameple 'attr: val;'. '$ (232.3)' was given

I know that I can use .format({"A": "${:,.0f}"}) for each column, but I want to format conditionaly some columns after those style methods, keeping that and other methods that changes colors based on values. Is there any easy way to achieve that result?

1

There are 1 answers

0
Tom Wagg On BEST ANSWER

The reason .map() is throwing an error is because that expects you to pass a function that returns CSS-styling, not a formatted string (see docs). E.g. something like background-color: 'red';

You can use your parent function in a .format() call though and that won't change the underlying data or colors. So that should allow you to apply your other conditions too. For example (with a slightly cleaner parent function):

def parent(x):
    if isinstance(x, float):
        return f"${x:,.0f}" if x >= 0 else f"$({abs(x):,.0f})"
    else:
        return x
df_stl = df.style.background_color(axis=None, subset=["A", "B"], cmap='autumn').format(parent)

enter image description here

Applying formatting to only a single column

[Update based on comments]

If you'd like to only apply your parent function to a single column, you can do this by instead passing a dictionary. Let's say you want to format column "A" with parent , you'd just do this:

df_stl = df.style.background_color(axis=None, subset=["A", "B"], cmap='autumn').format({"A": parent})

If you also wanted to style column "B" with other_style_function then just do

df_stl = df.style.background_color(axis=None, subset=["A", "B"], cmap='autumn').format({"A": parent, "B": other_style_function})