Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pandas style: How to highlight diagonal elements

I was wondering how to highlight diagonal elements of pandas dataframe using df.style method.

I found this official link where they discuss how to highlight maximum value, but I am having difficulty creating function to highlight the diagonal elements.

Here is an example:

import numpy as np
import pandas as pd

df = pd.DataFrame({'a':[1,2,3,4],'b':[1,3,5,7],'c':[1,4,7,10],'d':[1,5,9,11]})

def highlight_max(s):
    '''
    highlight the maximum in a Series yellow.
    '''
    is_max = s == s.max()
    return ['background-color: yellow' if v else '' for v in is_max]

df.style.apply(highlight_max)

This gives following output: enter image description here

I am wanting a yellow highlight across the diagonal elements 1,3,7,11 only.

How to do that?

like image 303
BhishanPoudel Avatar asked Jul 06 '19 17:07

BhishanPoudel


People also ask

How do I use conditional formatting in Pandas?

One way to conditionally format your Pandas DataFrame is to highlight cells which meet certain conditions. To do so, we can write a simple function and pass that function into the Styler object using . apply() or .

What is slicing in Pandas?

Slicing using the [] operator selects a set of rows and/or columns from a DataFrame. To slice out a set of rows, you use the following syntax: data[start:stop] . When slicing in pandas the start bound is included in the output. The stop bound is one step BEYOND the row you want to select.

How do you slice a panda array?

Slicing a DataFrame in Pandas includes the following steps:Ensure Python is installed (or install ActivePython) Import a dataset. Create a DataFrame. Slice the DataFrame.

How to highlight specific columns of a pandas Dataframe?

Let us see how to highlight specific columns of a Pandas DataFrame. We can do this using the apply () function of the Styler class. func : function should take a Series or DataFrame (depending on-axis), and return an object with the same shape. Must return a DataFrame with identical index and column labels when axis = None.

How do you style a pandas Dataframe?

Pandas Styling API As we mentioned pandas also have a styling system that lets you customize some aspects of its the rendered dataframe, using CSS. You write a “style functions” that take scalars, DataFrame or Series, and return like-indexed DataFrames or Series with CSS "attribute: value" pairs for the values.

How to create a bar chart inside a pandas Dataframe?

The Styler instance provides us with a method named bar () which lets us create a bar chart inside of the data frame. bar (subset=None,axis=0,color='#d65f5f',width=100, align='left') - This method can create bar inside of pandas data frame based on the value of that cell.

What is pandas in Python Dataframe?

In a nutshell, Pandas does everything you need to explore your datasets in Python. If you ever try to explain data by showing your raw DataFrame to someone, you will confuse them more than providing understanding. Styling your DataFrame to make what is important stand out will help you deliver the message more clearly.


3 Answers

Using axis=None we can use numpy to easily set the diagonal styles (Credit for this goes to @CJR)

import numpy as np
import pandas as pd

def highlight_diag(df):
    a = np.full(df.shape, '', dtype='<U24')
    np.fill_diagonal(a, 'background-color: yellow')
    return pd.DataFrame(a, index=df.index, columns=df.columns)

df.style.apply(highlight_diag, axis=None)

enter image description here


Original, really hacky solution

a = np.full(df.shape, '', dtype='<U24')
np.fill_diagonal(a, 'background-color: yellow')
df_diag = pd.DataFrame(a,
                       index=df.index,
                       columns=df.columns)

def highlight_diag(s, df_diag):
    return df_diag[s.name]

df.style.apply(highlight_diag, df_diag=df_diag)
like image 56
ALollz Avatar answered Nov 03 '22 02:11

ALollz


The trick is to use the axis=None parameter of the df.style.apply function in order to access the entire dataset:

import numpy as np
import pandas as pd

df = pd.DataFrame({'a':[1,2,3,4],'b':[1,3,5,7],'c':[1,4,7,10],'d':[1,5,9,11]})

def highlight_diag(data, color='yellow'):
    '''
    highlight the diag values in a DataFrame
    '''
    attr = 'background-color: {}'.format(color)
    # create a new dataframe of the same structure with default style value
    df_style = data.replace(data, '')
    # fill diagonal with highlight color
    np.fill_diagonal(df_style.values, attr)
    return df_style

df.style.apply(highlight_diag, axis=None)

output

like image 20
iyunbo Avatar answered Nov 03 '22 02:11

iyunbo


The other answer is pretty good but I already wrote this so....

def style_diag(data):
    diag_mask = pd.DataFrame("", index=data.index, columns=data.columns)
    min_axis = min(diag_mask.shape)
    diag_mask.iloc[range(min_axis), range(min_axis)] = 'background-color: yellow'
    return diag_mask

df = pd.DataFrame({'a':[1,2,3,4],'b':[1,3,5,7],'c':[1,4,7,10],'d':[1,5,9,11]})
df.style.apply(style_diag, axis=None)
like image 39
CJR Avatar answered Nov 03 '22 01:11

CJR