Pandas多列不同规则条件格式化优化及PNG保存求助
解决方案:DataFrame条件格式优化与导出PNG
一、优化条件格式函数(解决Series折叠错误)
你遇到的错误是因为Styler.apply要求返回的样式对象必须和原DataFrame维度完全匹配,此前的函数可能在处理时返回了Series而非二维样式矩阵。以下是封装好的可复用函数,针对不同列组精准应用格式化规则:
1. 构造测试DataFrame(用于验证)
import pandas as pd import numpy as np df = pd.DataFrame({ 'business_entity': ['A', 'B', 'C', 'D'], '2021-H1': [90, 85, 78, 92], '2022-H1': [88, 79, 89, 75], '2022-H2': [70, 82, 95, 80], 'Movement': [0.06, -0.03, -0.07, 0.02] })
2. 封装样式函数
def style_performance_table(df): # 定义分数列(2021-H1至2022-H2)的样式规则 def format_score(val): if val >= 89: return 'background-color: #7ccd7c' # 绿色 elif 79.5 <= val < 89: return 'background-color: #ffb966' # 橙色 else: return 'background-color: #ff6b6b' # 红色 # 定义Movement列的样式规则 def format_movement(val): if val >= 0.05: return 'background-color: #7ccd7c' elif -0.05 < val < 0.05: return 'background-color: #ffb966' else: return 'background-color: #ff6b6b' # 创建Styler对象,分列组应用规则 styler = df.style # 对目标分数列应用样式 styler = styler.applymap(format_score, subset=['2021-H1', '2022-H1', '2022-H2']) # 对Movement列单独应用样式 styler = styler.applymap(format_movement, subset=['Movement']) # 可选:增强表头可读性 styler = styler.set_table_styles([ {'selector': 'th', 'props': [('background-color', '#f0f0f0'), ('font-weight', 'bold')]} ]) return styler
3. 调用方式
styled_df = style_performance_table(df) # Jupyter环境下直接运行即可显示带格式的表格 styled_df
关键优化点:
- 使用
applymap而非apply,逐元素处理确保返回样式与原DataFrame维度完全匹配 - 通过
subset参数精准指定需要格式化的列,避免处理business_entity这类无需样式的列,从根源上避免结构不匹配问题
二、将带格式的表格保存为PNG文件
Pandas Styler本身不支持直接导出PNG,以下提供两种可行方案:
方案1:使用Matplotlib渲染导出(无外部依赖)
import matplotlib.pyplot as plt from pandas.plotting import table fig, ax = plt.subplots(figsize=(8, 3)) # 调整尺寸适配表格 ax.axis('off') # 隐藏坐标轴 tbl = table(ax, df, loc='center', cellLoc='center') # 手动应用背景色规则 for col_idx, col_name in enumerate(df.columns): # 处理分数列 if col_name in ['2021-H1', '2022-H1', '2022-H2']: for row_idx in range(len(df)): val = df.iloc[row_idx, col_idx] if val >= 89: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#7ccd7c') elif 79.5 <= val < 89: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#ffb966') else: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#ff6b6b') # 处理Movement列 elif col_name == 'Movement': for row_idx in range(len(df)): val = df.iloc[row_idx, col_idx] if val >= 0.05: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#7ccd7c') elif -0.05 < val < 0.05: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#ffb966') else: tbl.get_celld()[(row_idx+1, col_idx)].set_facecolor('#ff6b6b') # 设置表头样式 for col_idx in range(len(df.columns)): tbl.get_celld()[(0, col_idx)].set_facecolor('#f0f0f0') tbl.get_celld()[(0, col_idx)].set_text_props(weight='bold') # 保存为PNG plt.savefig('performance_table.png', dpi=300, bbox_inches='tight') plt.close()
方案2:使用imgkit(更简便,需外部工具)
- 先安装依赖:
pip install imgkit # 安装wkhtmltopdf: # Windows:下载安装后添加到系统环境变量;Linux:sudo apt-get install wkhtmltopdf;Mac:brew install wkhtmltopdf
- 转换代码:
import imgkit import os # 将带样式的表格转为HTML html_content = styled_df.to_html() # 临时保存HTML文件 with open('temp_table.html', 'w', encoding='utf-8') as f: f.write(html_content) # 转换为PNG imgkit.from_file('temp_table.html', 'performance_table.png', options={'quiet': ''}) # 可选:删除临时HTML文件 os.remove('temp_table.html')
内容的提问来源于stack exchange,提问作者Jay Cheng
相关产品推荐
相关产品推荐

