You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 22:00:17