Row formatting is essential when presenting tabular data, allowing you to highlight outliers, visualize trends, or simply improve readability. While Python's standard output can be formatted with strings, the most powerful row formatting capabilities exist within the Pandas library for data analysis.
This guide focuses on using the Pandas Styler object to apply custom CSS styling to rows based on specific data conditions.
Understanding the Pandas Styler
Pandas DataFrames have a .style property that returns a Styler object. This object allows you to apply CSS styling to the rendered HTML representation of the DataFrame (commonly used in Jupyter Notebooks or when exporting to HTML/Excel).
The key method is .apply(), which passes data (either column-wise or row-wise) to a styling function.
Method 1: Formatting Rows Based on Conditions
To style an entire row based on the value of a specific column, you must use df.style.apply(func, axis=1). The axis=1 ensures the function iterates over rows, not columns.
The Logic
The styling function must return a list of CSS strings exactly matching the number of columns in the row.
Dealing with Shape Mismatch Errors
A common mistake is returning a single string or a list of the wrong length.
import pandas as pd
import numpy as np
data = {
'Employee': ['Alice', 'Bob', 'Charlie', 'David'],
'Department': ['Sales', 'IT', 'Sales', 'HR'],
'Performance': [95, 70, 88, 60]
}
df = pd.DataFrame(data)
def incorrect_highlight(row):
if row['Performance'] < 65:
return 'background-color: red' # Error!
return ''
try:
df.style.apply(incorrect_highlight, axis=1)
except Exception as e:
print(f"Error: {e}")Output:
Error: Function returned 'str' object, but expected a list-like object of length 3Correct Approach
You must generate a list of strings, one for each column.
import pandas as pd
import numpy as np
data = {
'Employee': ['Alice', 'Bob', 'Charlie', 'David'],
'Department': ['Sales', 'IT', 'Sales', 'HR'],
'Performance': [95, 70, 88, 60]
}
df = pd.DataFrame(data)
def highlight_low_performance(row):
if row['Performance'] < 65:
return ['background-color: #ffcccc; color: black'] * len(row)
elif row['Performance'] > 90:
return ['background-color: #ccffcc; color: black'] * len(row)
else:
return [''] * len(row)
styled_df = df.style.apply(highlight_low_performance, axis=1)
print("Styling applied successfully.")Method 2: Formatting Specific Cells within Rows
Sometimes you want to analyze a row, but only highlight specific columns (e.g., if a student fails math, highlight only the math grade, not their name).
import pandas as pd
import numpy as np
data = {
'Employee': ['Alice', 'Bob', 'Charlie', 'David'],
'Department': ['Sales', 'IT', 'Sales', 'HR'],
'Performance': [95, 70, 88, 60]
}
df = pd.DataFrame(data)
def highlight_specific_cells(row):
styles = [''] * len(row)
if row['Department'] == 'Sales':
idx = row.index.get_loc('Employee')
styles[idx] = 'font-weight: bold; color: blue'
return styles
styled_df_specific = df.style.apply(highlight_specific_cells, axis=1)Method 3: Exporting Formatted Data
Styles applied via Pandas are not saved in CSV files (which are plain text). To preserve row formatting, you must export to Excel or HTML.
try:
styled_df.to_excel('styled_report.xlsx', engine='openpyxl', index=False)
print("Exported to styled_report.xlsx")
except ImportError:
print("Please install openpyxl: pip install openpyxl")
html_output = styled_df.to_html()
with open("report.html", "w") as f:
f.write(html_output)Conclusion
Custom row formatting in Python relies heavily on the Pandas Styler object.
- Use
df.style.apply(func, axis=1)to process data row-by-row. - Match Dimensions: Your styling function must return a list of CSS strings equal to the number of columns.
- Chain Methods: Combine multiple styling functions for complex visualizations.
- Export Properly: Save as Excel or HTML to retain the visual formatting.