使用R的pdftools读取PDF表格时,如何解决备注列引发的列偏移问题?
解决PDF表格读取的列偏移与多行合并问题
问题背景
用R的pdftools编写的PDF表格读取函数,基础读取功能正常,但遇到两个核心问题:
- 表格存在仅部分填充的备注列,导致带备注的行数据出现列偏移(如当前输出第8行、第15行的备注内容错位到最后一列);
- 部分长项目名称被拆分为多行,进一步加剧数据错位(如“Fair-value movement of investment properties”被拆成两行)。
核心解决方案
放弃依赖空格拆分的不可靠方式,改用固定列位置截取(PDF表格列是绝对对齐的,有固定起始/结束位置),同时先合并拆分的多行项目名称,再处理列数据。
具体实现代码
# 加载所需包 library(pdftools) library(stringr) # 目标PDF链接 url <- "https://www.rymanhealthcare.co.nz/hubfs/Investor%20Centre/Financial/Half%20year%20results%202022/Ryman%20Healthcare%20Limited%20-%20Announcement%20Numbers%20and%20financial%20statements%20-%2030%20September%202022.pdf" pdf_data <- pdf_text(url) # 修正后的PDF表格读取函数 scrape_pdf_fixed <- function(pdf_text, table_number, column_positions, column_names, first_row, last_row) { # 提取目标页码的文本并拆分行 page_text <- pdf_text[table_number] page_lines <- str_split(page_text, "\n")[[1]] %>% trimws() # 过滤空行 page_lines <- page_lines[page_lines != ""] # 定位目标表格的行范围 start_idx <- min(grep(first_row, page_lines)) end_idx <- max(grep(last_row, page_lines)) table_lines <- page_lines[start_idx:end_idx] # 合并多行项目名称:将无数值的行与下一行合并 merged_lines <- c() i <- 1 while(i <= length(table_lines)) { # 判断当前行是否包含数值(匹配数字或带括号的负数格式) has_value <- str_detect(table_lines[i], "\\d|\\(\\d") if(!has_value && i < length(table_lines)) { merged_lines <- c(merged_lines, paste(table_lines[i], table_lines[i+1])) i <- i + 2 } else { merged_lines <- c(merged_lines, table_lines[i]) i <- i + 1 } } # 按固定列位置截取每一列内容的辅助函数 extract_column <- function(line, start, end) { substr(line, start, end) %>% trimws() } # 提取所有列数据 table_data <- lapply(merged_lines, function(line) { sapply(1:length(column_positions), function(col) { pos <- column_positions[[col]] extract_column(line, pos[1], pos[2]) }) }) %>% do.call(rbind, .) %>% as.data.frame() # 设置列名,将空字符串转为NA colnames(table_data) <- column_names table_data[table_data == ""] <- NA return(table_data) } # 定义列的起始-结束位置(根据PDF表格实际布局调整) column_positions <- list( c(1, 45), # 项目列 c(46, 60), # 2022半年列 c(61, 75), # 2021半年列 c(76, 90), # 2022全年列 c(91, 100) # 备注列 ) column_names <- c("Item","6m 30-9-2022","6m 30-9-2021","12m 30-3-2022","Remarks") # 运行函数获取修正后的数据 fixed_output <- scrape_pdf_fixed(pdf_data, 3, column_positions, column_names, "Care fees", "Basic and diluted")
修正效果
原本错位的行数据会被正确拆分,备注列内容归位,多行项目名称合并为完整内容:
# 关键行示例输出 fixed_output[c(7,14),] #> Item 6m 30-9-2022 6m 30-9-2021 12m 30-3-2022 Remarks #>7 Fair-value movement of investment properties 3 261,346 285,143 745,885 #>14 Impairment loss 2 (10,784) - -
关键说明
- 固定列位置:PDF表格的列是绝对对齐的,用
substr截取比空格拆分更稳定,列位置可通过打印原始行、观察字符位置调整; - 多行合并:通过判断行是否包含数值,自动合并拆分的项目名称行,避免表头拆分导致的数据错位;
- 空值标准化:将空字符串转为NA,方便后续数据清洗与分析。
内容的提问来源于stack exchange,提问作者Webko Wuite
相关产品推荐
相关产品推荐

