In Python data analysis, presenting raw data can often be overwhelming. Visual cues, such as highlighting specific rows based on criteria (e.g., high risk, failing grades, or outliers), significantly improve readability. The primary tool for this in the Python ecosystem is the Pandas Styler API.
This guide explains how to apply custom CSS styles to DataFrame rows based on data conditions using pandas.DataFrame.style.
Understanding the Pandas Styler
Pandas DataFrames have a .style property that returns a Styler object. This object renders the data as HTML (for Jupyter Notebooks or web reports) and allows you to apply CSS.
To style rows, we use the .apply() method with axis=1.
axis=0: Apply function column-wise.axis=1: Apply function row-wise (this is what we want).axis=None: Apply function element-wise (entire table).
Method 1: Conditional Row Highlighting
The most common use case is highlighting a row if a specific column meets a condition.
Step-by-Step Implementation:
- Define a function that takes a row (Series).
- Check the condition on a specific column.
- Return a list of CSS strings matching the row length.
import pandas as pd
data = {
'Project': ['Alpha', 'Beta', 'Gamma', 'Delta'],
'Status': ['Complete', 'In Progress', 'Failed', 'Complete'],
'Budget': [10000, 25000, 5000, 12000]
}
df = pd.DataFrame(data)
def highlight_failed_rows(row):
if row['Status'] == 'Failed':
return ['background-color: #ffcccc; color: red'] * len(row)
else:
return [''] * len(row)
styled_df = df.style.apply(highlight_failed_rows, axis=1)
display(styled_df) Result: The row for Project "Gamma" will have a light red background and red text.
Method 2: Multi-Condition (Gradient) Styling
You can apply complex logic, such as a traffic light system, by expanding the if/elif/else logic within your styling function.
import pandas as pd
df = pd.DataFrame({
'Student': ['Alice', 'Bob', 'Charlie', 'David'],
'Score': [95, 55, 75, 88]
})
def grade_traffic_light(row):
score = row['Score']
green = 'background-color: #d4edda; color: #155724' # Pass
yellow = 'background-color: #fff3cd; color: #856404' # Average
red = 'background-color: #f8d7da; color: #721c24' # Fail
default = ''
if score >= 90:
style = green
elif score >= 60:
style = yellow
else:
style = red
return [style] * len(row)
styled_report = df.style.apply(grade_traffic_light, axis=1)
display(styled_report)Common Error: Shape Mismatch
A frequent ValueError occurs when the styling function returns a single string instead of a list, or a list of the wrong length. Pandas expects the returned styles to map 1-to-1 with the cells in that row.
Example of Error
import pandas as pd
df = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
def broken_highlighter(row):
if row['A'] > 1:
return 'background-color: yellow'
return ''
try:
df.style.apply(broken_highlighter, axis=1).to_html()
except Exception as e:
print(f"Error: {e}")Output:
Error: Function returned scalar: 'background-color: yellow'
... expecting list-like with length 2Solution
Ensure the return value is a list multiplied by len(row).
def fixed_highlighter(row):
if row['A'] > 1:
return ['background-color: yellow'] * len(row)
return [''] * len(row)
html_output = df.style.apply(fixed_highlighter, axis=1).to_html()
print("Styling applied successfully.")Conclusion
To apply custom formats to table rows in Python Pandas:
- Define a Function: Create a Python function that accepts a
row(Series). - Logic: Inside the function, check your data conditions (e.g.,
if row['val'] > 0). - Return Format: Return a list of CSS strings (
['style: val'] * len(row)). - Apply: Use
df.style.apply(func, axis=1)to render the changes.
This technique allows you to export professional, readable HTML tables or Excel sheets directly from your data analysis scripts.