bismo
bismo

Reputation: 1439

How to style all cells in a row of a specific MultiIndex value in pandas

SETUP

I have the following df:

import pandas as pd
import numpy as np

arrays = [
    np.array(["fruit", "fruit", "fruit","vegetable", "vegetable", "vegetable"]),
    np.array(["one", "two", "total", "one", "two", "total"]),
]

df = pd.DataFrame(np.random.randn(6, 4), index=arrays)

df.index.set_names(['item','count'],inplace=True)

WHAT I AM TRYING TO DO

I am trying to style df so that each cell where count == 'total' is bolded.

WHAT I HAVE TRIED

I was able to index all rows where count == 'total' with the following code:

idx = pd.IndexSlice
totals = df.loc[idx[:, 'total'],:]

but when I try to apply a function:

def df_style(val):
    return "font-weight: bold"

df.style.applymap(df_style,subset=totals)

I get the following error:

KeyError: 0

How can I style this df so that all cells where count == 'total' are bolded?

Here is a similar question, albeit with just a regular index rather than MultiIndex.

Upvotes: 1

Views: 39

Answers (1)

ouroboros1
ouroboros1

Reputation: 14184

Here's one approach:

# used `np.random.seed(0)` for reproducibility

def highlight_total(s):
    m = s.index.get_level_values('count') == 'total'
    return np.where(m, 'font-weight: bold', None)
    
df.style.apply(highlight_total)

Output:

df with total rows in bold

Explanation


Specifically traversing the df row-wise, you could do:

def highlight_total(s):
    return ['font-weight: bold']*len(s) if s.name[1] == 'total' else [None]*len(s)
    
df.style.apply(highlight_total, axis=1)

So, here we are accessing s.name[1], with name understood as ('fruit', 'total'), ('vegetable', 'total'), etc. Leads to the same result.

Upvotes: 2

Related Questions