如何用Python/Pandas自动识别多表头CSV的表头位置并提取信息
多块表头CSV的自动识别与提取方案
针对包含多个独立数据块的CSV文件,我们可以通过逐行分析的方式自动识别每个块的表头位置,并提取结构化的表头信息。
核心思路
你的CSV文件每个数据块遵循固定结构:
- 块标题行:仅第一个单元格有内容(如"Level and Distortion"),其余为空
- 通道/指标行:定义各数据列对应的通道或指标(如"Ch1 (F)")
- XY标识行:标记每列是X轴还是Y轴数据(如"X,Y,X,Y...")
- 单位行:定义各列数据的单位(如"Hz,Vrms...")
- 数据行:以数字开头,直到下一个块标题行出现
我们通过识别块标题行作为新块的起点,通过数据行的特征判断表头的终点,从而定位每个块的表头范围。
代码实现
import csv def identify_csv_headers(csv_path): headers_info = [] current_block = None with open(csv_path, 'r', newline='', encoding='utf-8') as f: reader = csv.reader(f) for line_num, row in enumerate(reader, start=1): # 清理行内容,去除引号和空单元格 cleaned_cells = [cell.strip('"') for cell in row] non_empty_cells = [cell for cell in cleaned_cells if cell] # 识别块标题行:仅一个非空单元格,且不是数据/表头关键字开头 if len(non_empty_cells) == 1: title = non_empty_cells[0] if not title.startswith(('X', 'Hz', 'Ch', 's')): # 保存上一个块(如果存在) if current_block: headers_info.append(current_block) # 初始化新块 current_block = { 'block_title': title, 'start_line': line_num, 'header_rows': [cleaned_cells] } continue # 处理当前块的表头行 if current_block is not None: # 判断是否是数据行:首单元格为数字(支持科学计数法) first_cell = cleaned_cells[0] if first_cell.replace('.', '').replace('E-', '').replace('E+', '').isdigit(): # 数据行开始,表头结束 current_block['end_line'] = line_num - 1 # 解析表头各层信息 current_block['channels'] = [cell for cell in current_block['header_rows'][1] if cell] current_block['xy_labels'] = [cell for cell in current_block['header_rows'][2] if cell] current_block['units'] = [cell for cell in current_block['header_rows'][3] if cell] headers_info.append(current_block) current_block = None else: # 加入表头行 current_block['header_rows'].append(cleaned_cells) # 处理最后一个未闭合的块 if current_block: current_block['end_line'] = line_num current_block['channels'] = [cell for cell in current_block['header_rows'][1] if cell] current_block['xy_labels'] = [cell for cell in current_block['header_rows'][2] if cell] current_block['units'] = [cell for cell in current_block['header_rows'][3] if cell] headers_info.append(current_block) return headers_info # 使用示例 if __name__ == "__main__": csv_path = "your_data.csv" result = identify_csv_headers(csv_path) # 打印提取的表头信息 for i, block in enumerate(result, 1): print(f"--- 数据块 {i} ---") print(f"标题: {block['block_title']}") print(f"表头行范围: 第 {block['start_line']} 行 至 第 {block['end_line']} 行") print(f"通道/指标: {block['channels']}") print(f"XY标识: {block['xy_labels']}") print(f"单位: {block['units']}\n")
代码说明
- 块标题识别:通过判断行内仅一个非空单元格,且内容不是数据行的关键字(如Hz、X、Ch)来定位新的数据块
- 表头范围确定:当遇到首单元格为数字(支持科学计数法)的行时,判定为数据行,此时前一行即为表头的最后一行
- 结构化提取:将每个块的表头拆分为通道/指标、XY标识、单位三个维度,方便后续处理
- 兼容性处理:考虑了CSV中的引号、空单元格,以及最后一个数据块的收尾逻辑
内容的提问来源于stack exchange,提问作者Muhammad Fauzan
相关产品推荐
相关产品推荐

