Multiple Styling Logic to Pandas DataFrame

Viewed 52

I want to apply background colors to a data frame using 4 different masking data frames. Each mask_df is the same shape as df. The colors will depend on which masks are true/false.


rndm = pd.DataFrame(np.random.uniform(-15,15,size=(100, 4)), columns=list('ABCD'))
rndm_mask1 = pd.DataFrame(np.random.choice([0,1],size=(100, 4), p=[2./3, 1./3]), columns=list('ABCD'))
rndm_mask2 = pd.DataFrame(np.random.choice([0,1],size=(100, 4), p=[1./3, 2./3]), columns=list('ABCD'))
rndm_mask3 = pd.DataFrame(np.random.choice([0,1],size=(100, 4), p=[2./3, 1./3]), columns=list('ABCD'))

Logic

Basically:

  1. if rndm_mask1 is true (and rndm_mask2 and 3 are FALSE), background is red
  2. if rndm_mask2 is true, yellow
  3. if rndm_mask3 is true, blue
  4. if rndm_mask1 AND rndm_mask2 are true, orange
  5. if rndm_mask2 AND rndm_mask3 are true, green
  6. if rndm_mask1 AND rndm_mask3 are true, purple

Problem:

I'm not sure how to chain all these styling logics into one cohesive function. The pd.DataFrame.style.apply() method requires list like outputs which I'm having trouble with.

Thanks!

1 Answers

You can first convert the mask to boolean with astype(bool) then use np.select

rndm_mask1 = rndm_mask1.astype(bool)
rndm_mask2 = rndm_mask2.astype(bool)
rndm_mask3 = rndm_mask3.astype(bool)

def styler(df):
    color = 'background-color: {}'.format

    m = np.select([rndm_mask1 & (~rndm_mask2) & (~rndm_mask3),
                   rndm_mask2, rndm_mask3,
                   rndm_mask1 & rndm_mask2,
                   rndm_mask2 & rndm_mask3,
                   rndm_mask1 & rndm_mask3],
                  list(map(color, ['red', 'yellow', 'blue', 'orange', 'green', 'purple'])),
              default='')

    return m


rndm = rndm.style.apply(styler, axis=None)
Related