Applying two styler functions simultanesouly to a dataframe

Question:

Here is the example script I am working with. I am trying to apply two styler functions to a dataframe at the same time but as you can see, it would only call the colors2 function. What would be the best way to apply two functions at the same time?

import pandas as pd
df = pd.DataFrame(data=[[-100,500,400,0,222,222], [9000,124,0,-147,54,-56],[77,0,110,211,0,222], [111,11,-600,33,0,22,],[213,-124,0,-147,54,-56]])
df.columns = pd.MultiIndex.from_product([['x','y','z'], list('ab')])

def colors(i):
    if i > 0:
        return 'background: red'
    elif i < 0:
        return 'background: green'
    elif i == 0:
        return 'background: yellow'
    else:
        ''
def colors2(i):
    if i < 0:
        return 'background: red'
    elif i > 0:
        return 'background: green'
    elif i == 0:
        return 'background: yellow'
    else:
        ''
idx = pd.IndexSlice
df.style.applymap (colors, subset=pd.IndexSlice[:, idx['x','b']])
df.style.applymap (colors2, subset=pd.IndexSlice[:, idx[:, 'b']])

enter image description here

Asked By: yeppi

||

Answers:

Chain your applymap commands in the desired order (last one prevails):

(df.style
   .applymap(colors2, subset=pd.IndexSlice[:, pd.IndexSlice[:, 'b']])
   .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice['x','b']])
 )

Here pd.IndexSlice['x','b']] is more restrictive than pd.IndexSlice[:, 'b'] so we use it last.

Another option could be to use a single function and to decide the color based on the labels inside it.

import numpy as np
def colors(s):
    if s.name[0] == 'x':
        s = s*-1
    return np.sign(s).map({-1: 'background: red', 1: 'background: green', 0: 'background: yellow'})
     
(df.style
   .apply(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:, 'b']])
 )

Output:

pandas multiple styles

Answered By: mozway