R语言批量提取PDF数据报错:pluck提示对象'_tmp_'未找到
问题解决建议
首先,你的循环代码存在语法错误,同时还有潜在的逻辑问题,一步步来修正:
1. 修复循环中的语法错误
你在管道链末尾直接写df[nrow(df) + 1, ] <- new是完全错误的语法——管道的每一步应该返回一个对象赋值给new,赋值操作不能嵌套在管道里。正确写法是先生成new对象,再完成对df的追加:
for (i in file_names) { # 跳过已经用来初始化的第一个PDF,避免重复添加 if (i == "firstlastname.pdf") next new <- extract_tables( file = i, method = "decide", output = "data.frame" ) %>% pluck(2, .default = NULL) %>% # 加默认值,避免找不到元素时报错 {if (!is.null(.)) t(.) else NULL} %>% as.data.frame() %>% slice(2) %>% select(1:3) %>% rename(inst = V1, date = V2, field = V3) # 只有当new有效时才追加 if (!is.null(new)) { df <- rbind(df, new) } }
2. 为什么之前能运行现在不行?
大概率是之前你的file_names列表里刚好没有重复的初始PDF,且所有PDF都能正常返回至少2个表格;而重启后可能目录里的PDF有变化,或者某个PDF解析后返回的表格数量不足2,导致pluck(2)找不到对象。加上.default = NULL和空值判断,能避免这种报错。
3. 更高效的替代写法(可选)
作为新手可以先掌握循环,但用purrr包的批量处理会更简洁,也更符合tidyverse风格:
library(purrr) # 定义处理单个PDF的函数 process_pdf <- function(file) { extract_tables(file = file, method = "decide", output = "data.frame") %>% pluck(2, .default = NULL) %>% {if (!is.null(.)) t(.) else NULL} %>% as.data.frame() %>% slice(2) %>% select(1:3) %>% rename(inst = V1, date = V2, field = V3) } # 批量处理所有PDF,过滤空值后合并 all_data <- map_dfr(file_names, process_pdf) # 若要保留初始df的逻辑,可单独处理第一个再合并 first_df <- process_pdf("firstlastname.pdf") other_df <- map_dfr(setdiff(file_names, "firstlastname.pdf"), process_pdf) df <- rbind(first_df, other_df)
额外提示
- 用
rbind(df, new)比直接赋值df[nrow(df)+1,] <- new更安全,后者在列数不匹配时会抛出模糊报错,而rbind会给出更清晰的提示。 - 可以在循环里加打印语句,比如
cat("正在处理:", i, "\n"),方便排查哪个PDF出了问题。
内容的提问来源于stack exchange,提问作者Hana Peri
相关产品推荐
相关产品推荐

