Search code examples
pythonpandasdataframestylesmultiple-columns

Mutilple style on part of DataFrame with two columns levels


I want to know how to apply multiple style on part of my df. I need to import the table on excel. I read all the doc https://pandas.pydata.org/docs/user_guide/style.html#Styler-Functions but some things are still hard to understand.

df = df.style.applymap(lambda x: f"background-color: {'#FFFFA7' if not isinstance(x, numbers.Number) else '#28D1C5' if x > 2 else '#FFC33C' if x < -2 else 'white'}").set_precision(2)

So, here you can see part of my df, with two level for columns. (I scribble for anonymity) my_table_1

With this code I manage to color (as I want) only the columns "Différence", but I want to keep the column "Avant".

main_tableau().iloc[:, main_tableau().columns.get_level_values(1)=='Différence'].style.applymap(lambda x: f"background-color: {'#FFFFA7' if not isinstance(x, numbers.Number) else '#28D1C5' if x > 2 else '#FFC33C' if x < -2 else 'white'}").format(precision=2)

my_table_2

Here is what I don't want, the columns 'Avant' with style. my_table_3

I try things like this to see if I manage tp apply style on my columns "différence" but it don't work: AttributeError: 'Styler' object has no attribute 'iloc'

df = df.style.applymap(lambda x: f"background-color: {'#FFFFA7' if not isinstance(x, numbers.Number) else '#28D1C5' if x > 2 else '#FFC33C' if x < -2 else 'white'}")\
            .applymap(lambda v: 'opacity: 20%;' if v in (main_tableau().iloc[:, main_tableau().columns.get_level_values(1)=='Différence']) else None).format(precision=2)

The result I want :

result

Edit : color


Solution

  • You can apply different styles to different subsets and chain the calls of apply / applymap:

    import pandas as pd
    import numpy as np
    import numbers
    
    np.random.seed(0)
    df = pd.DataFrame([list('abcdef')] + ((np.random.rand(5,6) - 0.5) * 10).tolist(),
                      columns=pd.MultiIndex.from_product([list('XYZ'), ['Avant', 'Différence']]),
                      index=list('abcdef'))
    
    (
     df.style.applymap(lambda x: f"background-color: {'#FFFFA7'}", subset=('a', ))
             .applymap(lambda x: f"background-color: {'#28D1C5' if x > 2 else '#FFC33C' if x < -2 else 'white'}", subset=(df.index[1:], (slice(None), 'Différence')))
             .applymap(lambda x: f"background-color: {'white'}", subset=(df.index[1:], (slice(None), 'Avant')))
             .format(precision=2)
    )
    

    enter image description here

    Please note that indices must be unique for this to work, but at least in the example you provided I think this is the case.