如何将PDF读取的原始行转为规范DataFrame?含pdf_data处理方案
基于PDF坐标文本生成规范DataFrame的解决方案
核心思路
利用pdf_data()返回的文本坐标信息,先按视觉行(y坐标)分组合并文本,再通过x坐标区间划分列,最后处理跨行的地址字段。
分步实现(R代码)
1. 读取并预处理坐标文本
library(pdftools) library(tidyverse) # 读取PDF的坐标化文本数据 pdf_text_data <- pdf_data("target_file.pdf") %>% bind_rows(.id = "page") %>% mutate(page = as.integer(page)) # 转换页码为整数
2. 按视觉行分组(解决跨行文本)
PDF中同一逻辑行的文本y坐标差异极小,通过设置阈值将相近y值的文本归为同一行:
# 行间距阈值(需根据PDF实际行高调整,通常3-10) y_threshold <- 5 text_with_row_groups <- pdf_text_data %>% group_by(page) %>% arrange(y) %>% # 计算相邻文本的y差值,超过阈值则新建行组 mutate(y_diff = y - lag(y, default = first(y)), row_group = cumsum(y_diff > y_threshold)) %>% ungroup() %>% # 同一行组内按x坐标排序,保证文本顺序与视觉一致 group_by(page, row_group) %>% arrange(x) %>% ungroup()
3. 按x坐标区间划分列
通过观察文本块的x分布,定义各列的x边界,将文本分配到对应列:
# 示例:根据PDF实际列位置定义x边界(需自行调整) column_x_bounds <- c(0, 120, 250, 400, Inf) # 对应列名 column_names <- c("序号", "姓名", "地址", "联系电话") text_with_columns <- text_with_row_groups %>% # 按x边界给文本分配列标识 mutate(column = cut(x, breaks = column_x_bounds, labels = column_names)) %>% # 同一行同一列的文本拼接(比如地址内的空格分隔文本) group_by(page, row_group, column) %>% summarise(text = str_c(text, collapse = " "), .groups = "drop") %>% # 宽格式转换,得到初步的行列表 pivot_wider(names_from = column, values_from = text)
4. 合并跨行的地址字段
针对地址分散在多行的情况,通过判断字段延续性(比如下一行无其他列数据)合并文本:
final_df <- text_with_columns %>% group_by(page) %>% mutate( # 标记需要合并的地址行:当前行地址非空、联系电话为空,且上一行地址非空 is_address_continuation = ifelse(!is.na(地址) & is.na(联系电话) & lag(!is.na(地址), default = FALSE), TRUE, FALSE), # 将延续的地址合并到上一行 地址 = ifelse(is_address_continuation, str_c(lag(地址), " ", 地址), 地址) ) %>% # 移除已被合并的行 filter(!is_address_continuation) %>% ungroup() %>% select(-is_address_continuation)
实用技巧
- 可视化文本位置:用
ggplot(pdf_text_data, aes(x, y, label = text)) + geom_text(size=2) + facet_wrap(~page)查看文本块分布,方便调整x边界和y阈值 - 调整列边界:通过
summary(pdf_text_data$x)查看x值分位数,快速确定列的分隔点 - 复杂跨行处理:若地址跨行且其他列有数据,可通过文本特征(如结尾为逗号、街道关键词)判断是否需要合并
内容的提问来源于stack exchange,提问作者Satya Pamidi
相关产品推荐
相关产品推荐

