R查找要从pdf中提取table的列表元素
R Find element of the list to extract table from pdf
我正在尝试使用 pdftools 包从 pdf 中提取数据 table。我的源文件在这里:https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf。比如说,我想从第 170 页的 Table 20 中提取数据(名义房价的变化)
我使用以下代码:
install.packages("pdftools")
library(pdftools)
report <- pdftools::pdf_data("https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf")
tab20 <- as.data.frame(report[170])
为了获得正确的 table,我必须手动指示我要提取列表的第 170 个元素(因为 table 在第 170 页)。如果明年,一个带有 table 的新页面被添加到报告中,我将不得不修改代码以提取第 171 个元素。有没有办法以更自动化的方式做到这一点?
基本上,我需要做的是找到包含字符串“Change in Nominal house price”的列表元素。有什么建议吗?
您可以找到具有相应模式的字符串。
通过使用多个过滤器,您可以收集这个单数 table.
table <- report[grepl('Change', report) & grepl('Nominal', report) &
grepl('house', report)]
我想更巧妙的正则表达式可以工作。这也是唯一有效的,因为没有其他 table 具有相同的标题,但最好检查它是否仅 return 如下所示的值:
place <- grepl('Change', report) &
grepl('Nominal', report) &
grepl('house', report)
if(sum(place) != 1){
stop("There is not only one pattern that match. Adjust pattern.")
} else {
table <- report[place]
}
编辑:要加快速度,您最好使用@Paul Smith 解决方案。
我用 grepl 和 lapply 对其进行了调整,速度更快!!!但是你需要确保标题完全没有改变。
system.time(
place <- unlist(lapply(report, function(x) grepl("Change in Nominal house price",
paste(x$text, collapse = " "))))
)
# user system spent
# 0.07 0.00 0.08
system.time(
place <- grepl('Change', report) & grepl('Nominal', report) &
grepl('house', report)
)
# user system spent
# 1.99 0.01 2.03
另一种解决方案,基于purrr::map_lgl
:
library(tidyverse)
library(pdftools)
report <- pdftools::pdf_data("https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf")
map_lgl(
report,
~ str_detect(
str_c(.x$text, collapse = " "),
"Change in Nominal house price")) %>% report[.]
#> [[1]]
#> # A tibble: 606 × 6
#> width height x y space text
#> <int> <int> <int> <int> <lgl> <chr>
#> 1 59 14 39 38 TRUE STATISTICAL
#> 2 35 14 102 38 FALSE TABLES
#> 3 25 26 33 81 TRUE 20.
#> 4 60 26 65 81 TRUE Change
#> 5 15 26 129 81 TRUE in
#> 6 67 26 149 81 TRUE Nominal
#> 7 47 26 221 81 TRUE house
#> 8 41 26 272 81 FALSE price
#> 9 30 14 65 103 TRUE Annual
#> 10 7 14 98 103 TRUE %
#> # … with 596 more rows
我正在尝试使用 pdftools 包从 pdf 中提取数据 table。我的源文件在这里:https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf。比如说,我想从第 170 页的 Table 20 中提取数据(名义房价的变化)
我使用以下代码:
install.packages("pdftools")
library(pdftools)
report <- pdftools::pdf_data("https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf")
tab20 <- as.data.frame(report[170])
为了获得正确的 table,我必须手动指示我要提取列表的第 170 个元素(因为 table 在第 170 页)。如果明年,一个带有 table 的新页面被添加到报告中,我将不得不修改代码以提取第 171 个元素。有没有办法以更自动化的方式做到这一点?
基本上,我需要做的是找到包含字符串“Change in Nominal house price”的列表元素。有什么建议吗?
您可以找到具有相应模式的字符串。 通过使用多个过滤器,您可以收集这个单数 table.
table <- report[grepl('Change', report) & grepl('Nominal', report) &
grepl('house', report)]
我想更巧妙的正则表达式可以工作。这也是唯一有效的,因为没有其他 table 具有相同的标题,但最好检查它是否仅 return 如下所示的值:
place <- grepl('Change', report) &
grepl('Nominal', report) &
grepl('house', report)
if(sum(place) != 1){
stop("There is not only one pattern that match. Adjust pattern.")
} else {
table <- report[place]
}
编辑:要加快速度,您最好使用@Paul Smith 解决方案。 我用 grepl 和 lapply 对其进行了调整,速度更快!!!但是你需要确保标题完全没有改变。
system.time(
place <- unlist(lapply(report, function(x) grepl("Change in Nominal house price",
paste(x$text, collapse = " "))))
)
# user system spent
# 0.07 0.00 0.08
system.time(
place <- grepl('Change', report) & grepl('Nominal', report) &
grepl('house', report)
)
# user system spent
# 1.99 0.01 2.03
另一种解决方案,基于purrr::map_lgl
:
library(tidyverse)
library(pdftools)
report <- pdftools::pdf_data("https://hypo.org/app/uploads/sites/2/2021/11/HYPOSTAT-2021_vdef.pdf")
map_lgl(
report,
~ str_detect(
str_c(.x$text, collapse = " "),
"Change in Nominal house price")) %>% report[.]
#> [[1]]
#> # A tibble: 606 × 6
#> width height x y space text
#> <int> <int> <int> <int> <lgl> <chr>
#> 1 59 14 39 38 TRUE STATISTICAL
#> 2 35 14 102 38 FALSE TABLES
#> 3 25 26 33 81 TRUE 20.
#> 4 60 26 65 81 TRUE Change
#> 5 15 26 129 81 TRUE in
#> 6 67 26 149 81 TRUE Nominal
#> 7 47 26 221 81 TRUE house
#> 8 41 26 272 81 FALSE price
#> 9 30 14 65 103 TRUE Annual
#> 10 7 14 98 103 TRUE %
#> # … with 596 more rows