基于百分位数为DataFrame单元格设置背景色
问题描述
我有一个包含多列多行的时间序列DataFrame df,通过以下代码读取:
df = pd.read_csv('percentiles.csv', index_col=0, parse_dates=True)
df 的最后3行数据如下:
| Date | ATH | ATL | 12MH | 12ML | 3MH | 3ML | 1MH | 1ML |
|---|---|---|---|---|---|---|---|---|
| 2024-02-16 | 6 | 0 | 8 | -1 | 11 | -8 | 15 | -16 |
| 2024-02-19 | 8 | -1 | 10 | -2 | 11 | -5 | 22 | -11 |
| 2024-02-20 | 8 | 0 | 13 | 0 | 16 | -2 | 40 | -3 |
我希望将该DataFrame导出为PDF表格,根据单元格在对应列中的数值高低设置背景色,采用百分位数方案实现。已通过以下代码计算各列的百分位数并生成 df2:
percentiles = [0, 0.1, 0.2, 0.8, 0.9] df2 = df.quantile(q=percentiles, axis=0)
df2 的内容如下:
| ATH | ATL | 12MH | 12ML | 3MH | 3ML | 1MH | 1ML | |
|---|---|---|---|---|---|---|---|---|
| 0.0 | 0.0 | -115.0 | 0.0 | -74.0 | 0.0 | -122.0 | 0.0 | -136.0 |
| 0.1 | 0.0 | -8.0 | 0.0 | -8.0 | 1.0 | -26.1 | 4.0 | -44.1 |
| 0.2 | 1.8 | -4.0 | 1.0 | -4.0 | 3.0 | -14.0 | 7.0 | -28.0 |
| 0.8 | 10.0 | 0.0 | 11.0 | 0.0 | 20.0 | -1.0 | 33.0 | -4.0 |
| 0.9 | 15.0 | 0.0 | 16.0 | 0.0 | 29.0 | 0.0 | 44.1 | -2.0 |
同时定义了百分位数与颜色的映射字典:
percentile_color = {0:'red', 0.1: 'orange', 0.2: 'white', 0.8: 'lightgreen', 0.9: 'green'}
我能为单个Series(列)实现该功能,但面对各列百分位数不同的DataFrame时遇到困难,寻求解决方案。
解决方案
通过逐列处理结合Pandas的Styler类,可为每列单元格匹配对应百分区间的背景色,最终导出为PDF。
步骤1:定义颜色匹配函数
针对每一列的百分位数区间,判断单元格数值所属区间并返回对应背景色样式:
def color_by_percentile(val, col_percentiles, color_map): # 遍历百分位数阈值,确定数值所在区间 for i in range(len(col_percentiles)-1): lower_q = col_percentiles.index[i] upper_q = col_percentiles.index[i+1] lower_val = col_percentiles.iloc[i] upper_val = col_percentiles.iloc[i+1] if lower_val <= val < upper_val: return f'background-color: {color_map[lower_q]}' # 处理大于等于0.9分位数的最大值区间 if val >= col_percentiles.loc[0.9]: return f'background-color: {color_map[0.9]}' # 处理小于0分位数的极端情况(理论上不会出现) return f'background-color: {color_map[0]}'
步骤2:为整个DataFrame应用样式
使用Styler.apply按列传递对应列的百分位数数据,批量设置单元格样式:
# 创建样式对象,按列处理每一列 styled_df = df.style.apply( lambda col: [color_by_percentile(x, df2[col.name], percentile_color) for x in col], axis=0 )
步骤3:导出为PDF表格
可通过以下两种方式导出:
方法1:直接导出PDF(需依赖weasyprint)
先安装依赖:
pip install weasyprint
然后导出:
styled_df.to_pdf('styled_percentiles.pdf', engine='weasyprint')
方法2:先导出HTML再转PDF(兼容更多工具)
# 导出为HTML文件 styled_df.to_html('styled_percentiles.html') # 可使用pdfkit、wkhtmltopdf等工具将HTML转为PDF
补充说明
- 函数会按
0→0.1→0.2→0.8→0.9→最大值的区间为单元格分配对应颜色,若需调整区间,只需修改percentiles列表和percentile_color字典; - 若
weasyprint安装遇到问题,推荐使用pdfkit配合wkhtmltopdf完成HTML转PDF的操作。
内容的提问来源于stack exchange,提问作者AndysPythonStuff
相关产品推荐
相关产品推荐

