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

Pandas清洗爬取PDF表格数据 合并错误拆分的多行记录

Pandas 异常拆分行合并高鲁棒性实现

问题特征

PDF表格解析时部分单行被错误拆分为3行,行特征固定:

  • 拆分首行:Item列存字符串片段,Quantity、Price为NaN
  • 拆分中间行:Item列为NaN,Quantity、Price存有效数值
  • 拆分末行:Item列存剩余字符串片段,Quantity、Price为NaN
    其余正常行所有字段均为有效值,需求为将3行拆分块合并为单条规整记录。

原有实现问题

基于索引硬偏移+逐行循环的写法鲁棒性极差:

  • 强依赖索引连续递增,只要索引断档、排序变动就会取错值
  • 无模式校验,遇到其他类型解析错误会静默输出错误结果
  • 逐行赋值性能差,数据量较大时运行效率极低

通用实现代码

核心逻辑为通过行特征打标、连续块分组聚合实现,完全不依赖硬编码行偏移:

import pandas as pd
import numpy as np

# 标记每行所属类型
df['row_type'] = np.where(
    df[['Quantity', 'Price']].isna().all(axis=1),
    np.where(df['Item'].notna(), 'split_part', 'unknown'),
    np.where(df['Item'].isna(), 'split_mid', 'normal')
)

# 生成连续分组ID:每遇到正常行/拆分块首行,分组ID自增,保证单条记录(无论正常还是拆分)同属一组
df['group_id'] = (df['row_type'].isin(['normal', 'split_part'])).cumsum()

# 按组聚合合并
merged_df = df.groupby('group_id', as_index=False).agg(
    # 拼接组内所有非空Item片段
    Item=('Item', lambda s: ' '.join(s.dropna().astype(str)).strip()),
    # 取组内第一个非空的数量、价格值
    Quantity=('Quantity', lambda s: s.dropna().iloc[0] if not s.dropna().empty else np.nan),
    Price=('Price', lambda s: s.dropna().iloc[0] if not s.dropna().empty else np.nan)
)

# 异常校验:输出未匹配模式的记录,方便排查脏数据
abnormal_records = merged_df[merged_df[['Item', 'Quantity', 'Price']].isna().any(axis=1)]
if not abnormal_records.empty:
    print(f"检测到{len(abnormal_records)}条不符合拆分模式的异常记录:")
    print(abnormal_records)

# 清理辅助列,输出最终规整结果
final_df = merged_df.drop(columns=['group_id']).dropna(subset=['Item', 'Quantity', 'Price'])

方案优势

  • 无索引依赖:不需要假设索引连续,DataFrame经过排序、筛选、重置索引后仍可正常运行
  • 自带异常校验:遇到不符合已知模式的脏数据会主动提示,不会静默生成错误结果
  • 性能优异:全Pandas原生向量化操作,相比逐行循环在万级以上数据量下性能提升10~100倍
  • 易扩展:后续新增其他表字段时,只需在agg聚合逻辑中补充对应字段的取值规则即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 03:03:39