Python中如何合并DataFrame并为原数据集添加分组标记列
实现方案
1. 先完成数据标记与合并
先给两个DataFrame分别加上class标记列,再用pd.concat合并,这一步是基础操作——虽然合并后每行都会显示标记值,但这是后续实现展示层单元格合并的必要前提:
import pandas as pd df1 = pd.DataFrame({'id': ['A01', 'A02'], 'Name': ['ABC', 'PQR']}) df2 = pd.DataFrame({'id': ['B05', 'B06'], 'Name': ['XYZ', 'TUV']}) # 给每个数据集添加专属标记 df1['class'] = 1 df2['class'] = 2 # 合并成一个DataFrame merged_df = pd.concat([df1, df2], ignore_index=True)
2. 实现展示层的单元格合并
你需要的是展示时同一原数据集的标记单元格合并,这属于可视化样式设置,而非数据结构层面的合并。下面分两种常用场景给出实现方法:
场景1:在Jupyter Notebook/IPython中展示
用Pandas的Styler工具,通过CSS样式实现相邻相同值的单元格合并:
def merge_class_cells(df): # 找出class列中重复的行 duplicate_mask = df['class'].duplicated(keep='first') style_rules = [] # 遍历每行,设置合并规则 for idx in range(len(df)): if not duplicate_mask.iloc[idx]: # 统计当前标记连续出现的行数 current_val = df['class'].iloc[idx] consecutive_count = 1 next_idx = idx + 1 while next_idx < len(df) and df['class'].iloc[next_idx] == current_val: consecutive_count += 1 next_idx += 1 # 给第一个单元格设置rowspan,合并后续相同值的单元格 style_rules.append({ 'selector': f'tbody tr:nth-child({idx+1}) td:nth-child(3)', 'props': [('vertical-align', 'middle'), ('text-align', 'center'), ('border', '1px solid #ccc'), ('rowspan', f'{consecutive_count}')] }) else: # 隐藏重复的单元格 style_rules.append({ 'selector': f'tbody tr:nth-child({idx+1}) td:nth-child(3)', 'props': [('display', 'none')] }) # 给表格添加基础边框 style_rules.append({ 'selector': 'table, th, td', 'props': [('border', '1px solid #ccc'), ('border-collapse', 'collapse')] }) return df.style.set_table_styles(style_rules) # 调用函数展示带合并单元格的表格 merge_class_cells(merged_df)
场景2:导出到Excel实现单元格合并
如果需要导出到Excel并保留合并效果,使用openpyxl库操作:
from openpyxl import Workbook from openpyxl.utils.dataframe import dataframe_to_rows from openpyxl.styles import Alignment # 创建工作簿和工作表 wb = Workbook() ws = wb.active # 将DataFrame数据写入工作表 for row_data in dataframe_to_rows(merged_df, index=False, header=True): ws.append(row_data) # 合并class列的相同单元格 current_class = None start_merge_row = 2 # 表头在第1行,数据从第2行开始 for row_num in range(2, ws.max_row + 1): current_val = ws.cell(row=row_num, column=3).value if current_val != current_class: # 合并上一组相同值的单元格 if current_class is not None: ws.merge_cells(start_row=start_merge_row, start_column=3, end_row=row_num-1, end_column=3) # 设置单元格内容居中对齐 ws.cell(row=start_merge_row, column=3).alignment = Alignment(vertical='center', horizontal='center') current_class = current_val start_merge_row = row_num # 处理最后一组相同值的单元格 ws.merge_cells(start_row=start_merge_row, start_column=3, end_row=ws.max_row, end_column=3) ws.cell(row=start_merge_row, column=3).alignment = Alignment(vertical='center', horizontal='center') # 保存Excel文件 wb.save('merged_data_with_class.xlsx')
内容的提问来源于stack exchange,提问作者Thomas Okonkwo
相关产品推荐
相关产品推荐

