如何用R将PDF书籍索引转换为指定格式的规范表格?
实现建议:从PDF索引页生成R表格
整体流程
核心思路是先提取PDF文本,利用缩进层级区分属/科、种加词、变种,再通过继承父级信息、拆分字段来构建目标表格。以下是具体步骤和代码示例:
步骤1:加载依赖包
需要用到pdftools提取文本,stringr处理字符串,dplyr/tidyr做数据整理:
library(pdftools) library(stringr) library(dplyr) library(tidyr)
步骤2:提取并清洗索引文本
先读取PDF的索引页,拆分成单行并过滤空行:
# 替换为你的PDF路径,指定索引所在页码范围 index_text <- pdf_text("your_book.pdf")[200:210] # 拆分单行、去除首尾空格、过滤空行 index_lines <- str_split(index_text, "\n") %>% unlist() %>% str_trim() %>% .[. != ""]
步骤3:识别缩进层级(关键)
缩进是区分层级的核心依据,统计每行开头的空格数(或制表符)来标记层级:
# 计算每行开头的空格数(如果是制表符,换成str_count(index_lines, "^\\t")) line_indent <- str_count(index_lines, "^\\s+") # 根据实际缩进规则标记层级: # - 0空格:属/科(首字母大写) # - 2-4空格:种加词(小写缩进) # - ≥6空格:变种(var开头,小写缩进) level <- case_when( line_indent == 0 ~ "genus_family", line_indent %in% c(2, 4) ~ "epithet", line_indent >= 6 ~ "underspp" )
步骤4:拆分名称与页码
按逗号拆分每行的物种名称和页码:
# 拆分名称部分和页码部分(逗号分隔,兼容逗号后有空格的情况) split_data <- str_split_fixed(index_lines, ",\\s*", 2) # 构建初始数据框 df <- tibble( level = level, name_part = str_trim(split_data[, 1]), no = as.integer(str_trim(split_data[, 2])) # 转成整数型页码 )
步骤5:继承父级信息
种加词需要关联上一级的属名,变种需要关联上一级的属和种加词:
# 向下填充属/科信息:种和变种继承最近的属/科 df <- df %>% fill(genus_family = ifelse(level == "genus_family", name_part, NA), .direction = "down") # 向下填充种加词信息:变种继承最近的种加词 df <- df %>% fill(epithet = ifelse(level == "epithet", name_part, NA), .direction = "down")
步骤6:整理成目标表格
匹配目标列的规则,清理冗余数据:
final_df <- df %>% mutate( # 第一列:属/科名称,种/变种行继承父级属/科 `genus/Family` = ifelse(level == "genus_family", name_part, genus_family), # 第二列:种加词,变种行继承父级种加词,属/科行设为NA epithet = case_when( level == "epithet" ~ name_part, level == "underspp" ~ epithet, TRUE ~ NA_character_ ), # 第三列:变种信息,仅变种行填充,其余设为NA underspp = ifelse(level == "underspp", name_part, NA_character_) ) %>% # 选择目标列,过滤无种/变种的纯属/科行(如果需要保留纯科/属行可删除此句) select(`genus/Family`, epithet, underspp, no) %>% filter(!is.na(epithet) | !is.na(underspp))
注意事项
- 缩进规则适配:不同PDF的缩进可能用空格或制表符,需要根据实际文本调整
line_indent的计算逻辑。 - 特殊情况处理:如果页码是范围(如
259-261),可以用str_split拆分成起始/结束页码,或保留字符串格式。 - 科层级兼容:如果索引包含科→属→种→变种的层级,需要调整
level的判断规则,增加科的层级标记。 - 大小写统一:可以用
str_to_lower()确保种加词和变种为小写,str_to_title()确保属/科首字母大写。
内容的提问来源于stack exchange,提问作者Anh
相关产品推荐
相关产品推荐

