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

如何聚合DataFrame使指定列值保留在独立单元格?

Pandas实现类似Excel合并单元格的分组展示效果

问题背景

现有如下Pandas DataFrame:

import pandas as pd

data = {
    'sto_num': [1, 1, 1, 2, 2, 3, 3],
    'sto_text': ['ab', 'ab', 'ab', 'k', 'k', 'b', 'b'],
    'tu_num': [2.2, 2.6, 3.5, 1.2, 1.3, 5.2, 5.1],
    'compliance': ['С', 'Н', 'Ч', 'С', 'Н', 'С', 'Ч'],
    'comment': ['с1', 'н1', 'ч1', 'с2', 'н2', 'с3', 'ч3']
}
df = pd.DataFrame(data)

原代码尝试通过groupby聚合将同组值合并到单个单元格,但需求是保留每行独立记录,仅在视觉上对sto_num列的重复值进行合并展示,类似Excel的合并单元格效果,同时疑问:DataFrame能否像Excel那样不同列拥有不同行数?

核心结论

Pandas DataFrame是严格的二维表格结构,每行的列数必须一致,无法实现某列单独多行的底层结构,但可以通过以下两种方式实现类似的视觉效果:

方法1:Jupyter Notebook中显示时合并重复单元格

通过Pandas的style功能自定义CSS样式,隐藏重复的sto_num单元格,仅显示每组的第一个值,视觉上实现合并效果,底层数据保持完整:

def merge_duplicate_display(df, target_col):
    col_idx = df.columns.get_loc(target_col) + 1  # CSS选择器从1开始计数
    styles = []
    # 遍历每个分组的索引范围
    for val, idx_list in df.groupby(target_col).groups.items():
        if len(idx_list) <= 1:
            continue
        # 设置第一个单元格垂直居中并占据多行高度
        styles.append({
            'selector': f'tbody tr:nth-child({idx_list[0]+1}) td:nth-child({col_idx})',
            'props': [
                ('vertical-align', 'middle'),
                ('border-bottom', 'none'),
                ('height', f'{len(idx_list)*30}px')
            ]
        })
        # 隐藏同组的其他单元格
        for idx in idx_list[1:]:
            styles.append({
                'selector': f'tbody tr:nth-child({idx+1}) td:nth-child({col_idx})',
                'props': [('display', 'none')]
            })
    return df.style.set_table_styles(styles)

# 应用样式并显示
styled_df = merge_duplicate_display(df, 'sto_num')
styled_df

方法2:导出到Excel时保留合并单元格

如果需要将结果导出为Excel文件并保留合并效果,可使用xlsxwriter引擎手动设置合并单元格:

with pd.ExcelWriter('grouped_output.xlsx', engine='xlsxwriter') as writer:
    df.to_excel(writer, sheet_name='Result', index=False)
    workbook = writer.book
    worksheet = writer.sheets['Result']
    
    # 遍历数据行,合并sto_num列的重复值
    prev_sto = None
    start_row = 1  # 表头行索引为0,数据从第1行开始
    total_rows = len(df)
    
    for row in range(1, total_rows + 1):
        current_sto = df.iloc[row-1]['sto_num']
        if current_sto != prev_sto:
            if prev_sto is not None:
                # 合并从start_row到当前行前一行的单元格
                worksheet.merge_range(f'A{start_row}:A{row-1}', prev_sto)
            prev_sto = current_sto
            start_row = row
    # 处理最后一组数据
    worksheet.merge_range(f'A{start_row}:A{total_rows}', prev_sto)

注意事项

  • 不要使用groupby聚合合并单元格,这会丢失原始行结构,不符合需求;
  • 上述方法仅改变展示/导出效果,底层DataFrame的每行记录保持独立,不影响后续数据分析操作。

内容的提问来源于stack exchange,提问作者user24958090

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:22:40