带多层索引的DataFrame样式设置及Excel导出问题求助
Pandas DataFrame Excel样式优化方案
原始DataFrame定义
import pandas as pd df = pd.DataFrame({ 'Counterparty': ['foo', 'fizz', 'fizz', 'fizz','fizz'], 'Commodity': ['bar', 'bar', 'bar', 'bar','bar'], 'DealType': ['Buy', 'Buy', 'Buy', 'Buy', 'Buy'], 'StartDate': ['07/01/2024', '09/01/2024', '10/01/2024', '11/01/2024', '12/01/2024'], 'FloatPrice': [18.73, 17.12, 17.76, 18.72, 19.47], 'MTMValue':[10, 10, 10, 10, 10] }) df = df.set_index(['Counterparty', 'Commodity', 'DealType','StartDate']).sort_index()[['FloatPrice', 'MTMValue']] print(df)
现有样式代码
def style_index(s): return "background-color: lightblue; text-align: center; border: 1px solid black; vertical-align: middle;" def style_header(s): return "background-color: lightgrey; text-align: center;" styled_df = df.style.set_properties(**{ 'background-color': 'darkblue', 'color': 'white', 'text-align': 'center'}).map_index(style_index).map_index(style_header, axis="columns")
现存问题
- 索引列的标题(
Counterparty、Commodity等索引名称)未高亮 - 索引项的水平居中未生效(仅实现垂直居中)
现有导出代码
with pd.ExcelWriter(path, engine='openpyxl', mode='a', if_sheet_exists='overlay') as writer: for item in list: styled_df = item.style.set_properties(**{ 'background-color': '#0F243E', 'color': 'white', 'text-align': 'center'}).map_index(style_index).map_index(style_header, axis="columns") styled_df.to_excel(writer, sheet_name=name, startrow=rowPos, float_format = "%0.2f", index=bool)
解决方案
1. 修复样式问题
Pandas的map_index默认仅作用于索引值,要设置索引列标题的样式,需用set_table_styles针对HTML标签定义样式,同时调整索引值的样式确保水平居中:
def style_index_cells(s): # 索引值样式:浅蓝色背景、水平+垂直居中、黑色边框 return "background-color: lightblue; text-align: center; vertical-align: middle; border: 1px solid black;" def style_column_headers(s): # 普通列标题样式:浅灰色背景、居中 return "background-color: lightgrey; text-align: center;" # 定义索引列标题的样式规则 table_styles = [ { 'selector': 'th.col_heading.level0', # 匹配多层索引的顶层索引列标题 'props': [ ('background-color', 'lightgrey'), ('text-align', 'center'), ('vertical-align', 'middle') ] } ] # 构建样式化DataFrame styled_df = df.style.set_properties(**{ 'background-color': '#0F243E', 'color': 'white', 'text-align': 'center', 'vertical-align': 'middle' }) \ .map_index(style_index_cells, axis=0) # 应用索引值样式 .map_index(style_column_headers, axis=1) # 应用普通列标题样式 .set_table_styles(table_styles) # 应用索引列标题样式
2. 优化导出代码
- 将样式逻辑封装为可复用函数,避免重复代码
- 规避Python内置关键字作为变量名(
list、bool)
def apply_dataframe_style(df): def style_index_cells(s): return "background-color: lightblue; text-align: center; vertical-align: middle; border: 1px solid black;" def style_column_headers(s): return "background-color: lightgrey; text-align: center;" table_styles = [ { 'selector': 'th.col_heading.level0', 'props': [ ('background-color', 'lightgrey'), ('text-align', 'center'), ('vertical-align', 'middle') ] } ] return df.style.set_properties(**{ 'background-color': '#0F243E', 'color': 'white', 'text-align': 'center', 'vertical-align': 'middle' }) \ .map_index(style_index_cells, axis=0) \ .map_index(style_column_headers, axis=1) \ .set_table_styles(table_styles) # 导出代码优化版 with pd.ExcelWriter(path, engine='openpyxl', mode='a', if_sheet_exists='overlay') as writer: # 替换内置关键字变量名:list→df_list,bool→index_flag for item in df_list: styled_df = apply_dataframe_style(item) styled_df.to_excel(writer, sheet_name=name, startrow=rowPos, float_format="%0.2f", index=index_flag)
补充说明
- 若使用单层索引,可将
table_styles中的selector改为'th.col_heading' - 封装后的样式函数可快速应用于多个DataFrame,便于后续维护修改
内容的提问来源于stack exchange,提问作者iBeMeltin
相关产品推荐
相关产品推荐

