Pandas Dataframe Examples: Styling Cells and Conditional Formatting
Last updated:- Style cell if condition
- Row-wise style
- Highlight cell if largest in column
- Apply style to column only
- Chain styles
- Multiple styles in same function
All code available on this jupyter notebook
Style cell if condition
Here we apply elementwise formatting, because the logic only depends on the single value itself.
Use df.applymap(styler_function) where styler_function takes a cell value and returns a CSS style
Example: Change background color for even numbers
import pandas as pd
df = pd.DataFrame({
"name": ["alan","beth","charlie","david", "edward"],
"age" : [34, 12, 43, 32, 77],
"num_children": [1, 0, 2, 1, 6],
"num_pets": [1, 0, 1, 2, 0],
"bank_balance": [100.0, 10.0, -10.0, 30.0, 30.0]})
def even_number_background(cell_value):
highlight = 'background-color: darkorange;'
default = ''
if type(cell_value) in [float, int]:
if cell_value % 2 == 0:
return highlight
return default
df.style.applymap(is_even_background)
Base dataframe
All even numbers had their background changed
Row-wise style
In other words: for row, take all values and decide which ones to style.
Use df.style.apply(func, axis=1). Use subset=[cols] to limit application to some columns only.
Example: Highlight whether each person has more children or more pets
import pandas as pd
df = pd.DataFrame({
"name": ["alan","beth","charlie","david", "edward"],
"age" : [34, 12, 43, 32, 77],
"num_children": [1, 0, 2, 1, 6],
"num_pets": [1, 0, 1, 2, 0],
"bank_balance": [100.0, 10.0, -10.0, 30.0, 30.0]})
def more_children_or_more_pets_background(row):
highlight = 'background-color: lightcoral;'
default = ''
# must return one string per cell in this row
if row['num_children'] > row['num_pets']:
return [highlight, default]
elif row['num_pets'] > row['num_children']:
return [default, highlight]
else:
return [default, default]
df.style.apply(more_children_or_more_pets_background, subset=['num_children', 'num_pets'], axis=1)
Base dataframe, unstyled.
Charlie and Edward have more children than pets, while David has more
pets than children.
Highlight cell if largest in column
That is, column-wise styling.
Use df.style.apply(func, axis=0)
Example: Change background colour in the maximum values for num_children and num_pets:
import pandas as pd
df = pd.DataFrame({
"name": ["alan","beth","charlie","david", "edward"],
"age" : [34, 12, 43, 32, 77],
"num_children": [1, 0, 2, 1, 6],
"num_pets": [1, 0, 1, 2, 0],
"bank_balance": [100.0, 10.0, -10.0, 30.0, 30.0]})
def maximum_value_in_column(column):
highlight = 'background-color: palegreen;'
default = ''
maximum_in_column = column.max()
# must return one string per cell in this column
return [highlight if v == maximum_in_column else default for v in column]
df.style.apply(maximum_value_in_column, subset=['num_children', 'num_pets'], axis=0)
Base dataframe
The maximum values for num_children and and num_pets are 6 and 2,
respectively.
Apply style to column only
In order to restrict application of some style to some columns, use subset=[cols]:
df.style.apply(func, subset=['col1'], axis=1)to applyfuncrowwise to column'col1'onlydf.style.apply(func, subset=['col2'], axis=0)to applyfunccolumnwise to column'col2'only
Chain styles
In other words, apply multiple styles one after the other:
In this example:
- use red font for negative values in
bank_balance - write the highest age in bold
- use light red background for zero values in
num_childrenandnum_pets
import pandas as pd
df = pd.DataFrame({
"name": ["alan","beth","charlie","david", "edward"],
"age" : [34, 12, 43, 32, 77],
"num_children": [1, 0, 2, 1, 6],
"num_pets": [1, 0, 1, 2, 0],
"bank_balance": [100.0, 10.0, -10.0, 30.0, 30.0]})
def red_font_negatives(series):
highlight = 'color: red;'
default = ''
return [highlight if e < 0 else default for e in series]
def bold_max_value_in_series(series):
highlight = 'font-weight: bold;'
default = ''
return [highlight if e == series.max() else default for e in series]
def red_background_zero_values(cell_value):
highlight = 'background-color: tomato;'
default = ''
if cell_value == 0:
return highlight
else:
return default
(df
.style
.apply(red_font_negatives, axis=0, subset=['bank_balance'])
.apply(bold_max_value_in_series, axis=0, subset=['age'])
.applymap(red_background_zero_values))
Base dataset, unstyled
Multiple stylings applied together: largest age in bold, zero values in
pets or children and negative
bank balances.
Multiple styles in same function
You can use multiple else clauses in a ternary if-else condition too:
import pandas as pd
df = pd.DataFrame({
"name": ["alan","beth","charlie","david", "edward"],
"bank_balance": [100.0, 10.0, -10.0, 30.0, 30.0]})
def colour_numbers(series):
red = 'background-color: red;'
orange = 'background-color: orange;'
default = ''
# note multiple else ..if conditions
return [red if e < 0 else orange if e < 15 else default for e in series]
(df
.style
.apply(colour_numbers, axis=0, subset=['bank_balance']))
BEFORE: no styling
AFTER: our logic now checks two conditions and depending
on which one matched, the cell
gets a different colour