读取含多级分组类透视CSV并转换为Pandas DataFrame的方法
这个问题我刚好处理过类似的,给你一套完整的解决方案,一步步来:
核心思路
你的数据是典型的层级缩进式透视数据,核心逻辑是:通过前导空格数确定每行的层级,追踪父层级的名称并向下填充到子节点,最后只保留最底层(Level4)的行,计算a-b的差值并整理成目标格式。
步骤1:读取并筛选有效数据
因为开头存在无关文本行,我们先读取所有行,动态定位到表头行(包含header A和header B的行),从下一行开始提取有效数据,这样不管开头有多少无关行都能准确识别。
步骤2:识别层级并追踪父节点
每行的前导空格数除以3就是对应的层级(0→Level0,3→Level1,…,12→Level4)。我们需要维护一个字典来记录当前各层级的名称:
- 遇到Level0行时,更新Level0的值,并重置Level1到Level4为空
- 遇到Level1行时,更新Level1的值,重置Level2到Level4为空,以此类推
- 只有当Level4有值时,说明这是一个叶子节点,我们才收集这条数据(因为你的示例结果只包含Level4的行)
步骤3:计算差值并调整列顺序
对每个叶子节点计算Diff(a,b) = a - b,最后把列调整成你需要的顺序:Level4, Diff(a,b), Level0, Level1, Level2, Level3
完整代码示例
import pandas as pd # 1. 读取文件并筛选有效数据 with open('your_data.csv', 'r') as f: lines = f.readlines() # 定位表头行(包含header A和header B的行) header_index = None for idx, line in enumerate(lines): if 'header A' in line and 'header B' in line: header_index = idx break # 提取表头之后的有效数据行 data_lines = lines[header_index + 1:] # 2. 处理每行,识别层级并追踪父节点 current_levels = { 'Level0': None, 'Level1': None, 'Level2': None, 'Level3': None, 'Level4': None } processed_rows = [] for line in data_lines: line = line.strip('\n') if not line: continue # 跳过空行 # 计算前导空格数,确定层级 leading_spaces = len(line) - len(line.lstrip()) level = leading_spaces // 3 # 分割行数据:名称、a值、b值(处理逗号后的空格) parts = [p.strip() for p in line.split(',')] node_name = parts[0] a_value = float(parts[1]) b_value = float(parts[2]) # 更新当前层级的名称,重置子层级 if level == 0: current_levels['Level0'] = node_name current_levels['Level1'] = None current_levels['Level2'] = None current_levels['Level3'] = None current_levels['Level4'] = None elif level == 1: current_levels['Level1'] = node_name current_levels['Level2'] = None current_levels['Level3'] = None current_levels['Level4'] = None elif level == 2: current_levels['Level2'] = node_name current_levels['Level3'] = None current_levels['Level4'] = None elif level == 3: current_levels['Level3'] = node_name current_levels['Level4'] = None elif level == 4: current_levels['Level4'] = node_name else: continue # 超出Level4的行忽略 # 只收集Level4存在的叶子节点数据 if current_levels['Level4'] is not None: processed_rows.append({ 'Level0': current_levels['Level0'], 'Level1': current_levels['Level1'], 'Level2': current_levels['Level2'], 'Level3': current_levels['Level3'], 'Level4': current_levels['Level4'], 'Diff(a,b)': a_value - b_value }) # 3. 生成目标DataFrame并调整列顺序 result_df = pd.DataFrame(processed_rows) result_df = result_df[['Level4', 'Diff(a,b)', 'Level0', 'Level1', 'Level2', 'Level3']] # 查看结果 print(result_df)
示例效果
假设你的CSV内容是:
无关文本行1 无关文本行2 header A, header B C, 1000, 475 c1, 800, 300 c2, 500, 200 c3, 600, 75 x7, 600, 75 D, 2000, 1000 d1, 1500, 800 d2, 900, 300 d3, 700, 100 x8, 700, 100
运行代码后会输出:
Level4 Diff(a,b) Level0 Level1 Level2 Level3 0 x7 525.0 C c1 c2 c3 1 x8 600.0 D d1 d2 d3
完全符合你给出的示例要求。
内容的提问来源于stack exchange,提问作者gussilago
相关产品推荐
相关产品推荐

