Jupyter Notebook中带缩进格式的DataFrame表格展示问题
实现Jupyter Notebook中表格的层级缩进(总计/小计)
需求说明
从数据库读取的多层索引表格,需要在Jupyter Notebook中展示时,让总计(total)、**小计(subtotal)**及明细项呈现层级缩进效果,同时添加线条、粗体等样式增强可读性。
原始数据
from pandas import MultiIndex, DataFrame, Series index = MultiIndex.from_tuples( [ ('total', 'subtotal', 'a'), ('total', 'subtotal', 'b'), ('total', 'subtotal', 'c'), ('total', 'subtotal', 'd'), ('total', 'foo', 'foo'), ('total', 'bar', 'bar') ], names=['module_1', 'module_2', 'module_3'] ) musd = [ 106.564338488296, 60.5686589737704, 311.695156173571, -90.3794796906721, 29.6147863260859, -49.0048344046974 ] # 从数据库加载的原始数据格式 df = Series(musd, index=index, name='musd').to_frame()
问题分析
之前尝试通过在字符串前添加空格实现缩进,但HTML表格会自动合并连续空格,导致缩进效果失效。需要通过CSS样式直接控制文本缩进,同时补充边框、粗体等样式。
解决方案:利用Pandas Styler实现CSS级控制
方法1:构建格式化DataFrame后应用样式
先整理包含明细、小计、总计的数据集,再通过Styler的CSS属性设置缩进和样式:
import pandas as pd # 计算小计和总计 subtotal_sum = df.xs(('total', 'subtotal'), level=['module_1', 'module_2'])['musd'].sum().round(1) total_sum = df['musd'].sum().round(1) # 构建带缩进层级的DataFrame formatted_data = [ ('a', 106.6, 4), ('b', 60.6, 4), ('c', 311.7, 4), ('d', -90.4, 4), ('subtotal', subtotal_sum, 2), ('foo', 29.6, 2), ('bar', -49.0, 2), ('total', total_sum, 0) ] formatted_df = pd.DataFrame(formatted_data, columns=['item', 'musd', 'indent']) # 定义样式应用函数 def apply_styles(row): style_list = [] # 按层级设置缩进(15px/层级) indent_px = row['indent'] * 15 style_list.append(f'text-indent: {indent_px}px;') # 小计、总计行加粗 if row['item'] in ['subtotal', 'total']: style_list.append('font-weight: bold;') # 小计行添加上边框 if row['item'] == 'subtotal': style_list.append('border-top: 1px solid #000;') # 总计行添加上下边框 if row['item'] == 'total': style_list.append('border-top: 2px solid #000; border-bottom: 1px solid #000;') # 给整行所有列应用样式 return style_list * len(row) # 应用样式并渲染表格 styled_table = formatted_df.style.apply(apply_styles, axis=1)\ .hide(axis='columns', subset=['indent'])\ .set_table_styles([ {'selector': 'table', 'props': [('border-collapse', 'collapse')]}, {'selector': 'th, td', 'props': [('border', '1px solid #ddd'), ('padding', '8px')]} ]) # 在Jupyter中显示表格 styled_table
方法2:基于原始多层索引直接设置样式
保留原始多层索引结构,根据索引层级自动设置缩进和样式:
# 构建包含汇总行的多层索引 summary_index = MultiIndex.from_tuples( [ ('total', 'subtotal', 'a'), ('total', 'subtotal', 'b'), ('total', 'subtotal', 'c'), ('total', 'subtotal', 'd'), ('total', 'subtotal', ''), # 小计行 ('total', 'foo', 'foo'), ('total', 'bar', 'bar'), ('total', '', '') # 总计行 ], names=['module_1', 'module_2', 'module_3'] ) # 填充明细和汇总数据 summary_data = df['musd'].round(1).tolist() + [subtotal_sum, 29.6, -49.0, total_sum] summary_df = pd.Series(summary_data, index=summary_index, name='musd').to_frame() # 针对索引层级设置样式 def style_by_index(row): level1, level2, level3 = row.name style_list = [] # 根据索引层级设置缩进 if level3 != '': style_list.append('text-indent: 40px;') # 明细行缩进 elif level2 != '': style_list.append('text-indent: 20px;') # 小计行缩进 style_list.append('font-weight: bold; border-top: 1px solid #000;') else: style_list.append('text-indent: 0;') # 总计行无缩进 style_list.append('font-weight: bold; border-top: 2px solid #000; border-bottom: 1px solid #000;') return style_list * len(row) # 渲染表格 summary_styled = summary_df.style.apply(style_by_index, axis=1)\ .set_table_styles([ {'selector': 'table', 'props': [('border-collapse', 'collapse')]}, {'selector': 'th, td', 'props': [('border', '1px solid #ddd'), ('padding', '8px')]} ]) summary_styled
关键说明
- 直接在字符串前加空格无效:HTML表格会自动合并连续空格,必须使用CSS的
text-indent属性控制缩进。 - 样式可灵活调整:通过修改
text-indent的像素值、边框样式、字体粗细等参数,可完全匹配预期的视觉效果。
内容的提问来源于stack exchange,提问作者mortysporty
相关产品推荐
相关产品推荐

