‹ Geoff Ruddock

df.style

Feb 07, 2021
import numpy as np
import pandas as pd

from IPython.core.display import HTML

from platform import python_version

print(f'python: {python_version()}')
print(f'pandas: {pd.__version__}')
python: 3.8.10
pandas: 1.2.4

Example dataframe

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charles', 'Denise', 'Eric', 'Fiona'],
    'age': np.random.randint(20, 80, size=6),
    'origin': ['New York', 'Toronto', 'Chicago', 'Berlin', 'Paris', 'Singapore'],
    'location': ['New York', 'Chicago', 'Chicago', 'Singapore', 'Paris', 'Singapore']
}).rename_axis('user_id')

df

name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

df.style.X

Styling should be performed after the data in a DataFrame has been processed. The Styler creates an HTML <table> and leverages CSS styling language to manipulate many parameters including colors, fonts, borders, background, etc.

The DataFrame.style attribute is a property that returns a Styler object. It has a _repr_html_ method defined on it so they are rendered automatically in Jupyter Notebook.

def hugo_safe_render(styler):
    """ Removes spacing from HTML output of df.style to prevent rendering issues in Hugo. """

    raw_html = styler.render()
    clean_html = ' '.join(raw_html.split())
    display(HTML(clean_html))

set_caption

(
    df
    .style
    .set_caption('This is an example DataFrame.')
    .pipe(hugo_safe_render)
)
This is an example DataFrame.
name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

Font

df.style.set_properties(**{'font-family': 'Menlo'}).pipe(hugo_safe_render)
name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

Background gradient

df.style.background_gradient(subset=['age'], cmap='Reds').pipe(hugo_safe_render)
name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

Recipes

Bold specific values

from functools import partial

def bold_rows(vals: list, x) -> str:
    """ Designed to be 'completed' using functools.partial,
    then fed into pandas.DataFrame.style.applymap(func) """
    
    if x in vals:
        return 'font-weight:bold'
    else:
        return ''

SOME_VALUES = ['New York', 'Toronto']

bold_some_values = partial(bold_rows, SOME_VALUES)

df.style.applymap(bold_some_values).pipe(hugo_safe_render)
name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

Highlight differences

from typing import List

def highlight_diff_styler(row: pd.Series, color='yellow') -> List[str]:
    """ The function to use in df.style.apply() """

    attr = 'background-color: {}'.format(color)
    is_diff = row.iloc[0] != row.iloc[1]
    if is_diff:
        return [attr, attr]
    else:
        return ['', '']
    

df.style.apply(highlight_diff_styler, axis=1, subset=['origin', 'location']).pipe(hugo_safe_render)
name age origin location
user_id
0 Alice 48 New York New York
1 Bob 53 Toronto Chicago
2 Charles 25 Chicago Chicago
3 Denise 61 Berlin Singapore
4 Eric 24 Paris Paris
5 Fiona 30 Singapore Singapore

📚 Further reading

comments powered by Disqus