Пакет Tabulizer в R: как скрести таблицы после определенного заголовка - PullRequest
0 голосов
/ 28 января 2019

Как очистить таблицы, перед которыми стоит какой-то текст заголовка из PDF?Я экспериментирую с пакетом tabulizer.Вот пример получения таблицы с определенной страницы (польская «Карта потребностей общественного здравоохранения»)

library(tabulizer)
library(tidyverse)
options(java.parameters = "-Xmx8000m")

location<-"http://www.mpz.mz.gov.pl/wp-content/uploads/sites/4/2019/01/mpz_choroby_ukladu_kostno_miesniowego_woj_dolnoslaskie.pdf"

(out<-extract_tables(location, pages = 8,encoding = "UTF-8", method = "stream", outdir = getwd())[[4]] %>%
as.tibble())

Это дает мне одну таблицу на конкретной странице.Но у меня будет много таких pdf-файлов, которые можно почистить, с сайта: http://www.mpz.mz.gov.pl/mapy-dla-30-grup-chorob-2018/, а затем подстраницы с множеством ссылок для каждой болезни, получая ссылки с помощью rvest, для каждой провинции Польши, и мне нужно почистить таблицы послеконкретная строка заголовка, например.

Tabela 1.2.2: структура западного общества с населением и средними ценами, в котором есть все, что нужно (

*)...) ", потому что таблицы не могут быть на одной странице.Большое спасибо за любые указания и идеи заранее.

РЕДАКТИРОВАТЬ: После того, как я задал вопрос, мне удалось найти страницы, где таблица может быть, может быть, очень неэффективно:

library(pdfsearch)

pages <-
  keyword_search(
    location,
    keyword = c(
      'Tabela',
      'Struktura zapadalnosci rejestrowanej'
    ),
    path = TRUE,
    surround_lines = FALSE
  ) %>%
  group_by(page_num) %>%
  mutate(keyword = paste0(keyword, collapse = ";")) %>%
  filter(
    str_detect(keyword, "Tabela") &
      str_detect(keyword, "Struktura zapadalnosci rejestrowanej")
  ) %>%
  pull(page_num) %>%
  unique()

Ответы [ 2 ]

0 голосов
/ 03 апреля 2019

Я могу помочь вам с вашей основной проблемой, но есть одна загвоздка (см. В конце).Я использую pdftools вместо pdfsearch, но в этом случае он делает то же самое (поиск страниц с таблицей).Чтобы сэкономить время, я загружаю PDF только один раз в начале:

options(java.parameters = "-Xmx8000m")# needs to be set before loading tabulizer
library(tabulizer)
library(tidyverse)

location <- "http://www.mpz.mz.gov.pl/wp-content/uploads/sites/4/2019/01/mpz_choroby_ukladu_kostno_miesniowego_woj_dolnoslaskie.pdf"
download.file(location, "test.pdf", mode = "wb")

Теперь преобразуйте PDF в файл data.frame с каждой строкой в ​​строке df:

raw <- pdftools::pdf_data("test.pdf") 
pages <- lapply(seq_along(raw), function(p) {
  if (nrow(raw[[p]]) > 0) {
    raw[[p]]$page <- p
    raw[[p]]
  }
}) %>% 
  bind_rows() %>% 
  group_by(y, page) %>% 
  summarise(text = paste(text, collapse = " ")) %>% 
  arrange(page, y)

Этот data.frame доступен для поиска, и мы сохраняем только строки, соответствующие вашему ключевому слову:

tables <- pages %>% 
  filter(grepl("Tabela .* Struktura zapadalnosci", text))

Есть 8 строк, которые соответствуют ключевой фразе.Из них мы извлекаем только таблицы.Кроме того, функция в цикле lapply поддерживает только матрицу с наибольшим количеством строк.Если на одной странице есть две таблицы, это может быть проблемой, но, как правило, хорошо использовать только «лучшее предположение», которое tabulizer сделал для нахождения структуры таблицы.

tables_list <- lapply(tables$page, function(p) {
  cat(p, "\n")
  out <- extract_tables("test.pdf", 
                        pages = p,
                        encoding = "UTF-8", 
                        method = "stream", 
                        output = "matrix")
  out <- as_tibble(out[[which.max(sapply(out, nrow) + sapply(out, ncol))]]) # keep the biggest table
  attr(out, "caption") <- tables$text[tables$page %in% p]
  return(out)
})

Объект tables_listтеперь содержит список data.frames, каждая преобразованная таблица:

> tables_list[[1]]
# A tibble: 16 x 8
   V1                  V2    V3    V4    V5    V6    V7    V8   
   <chr>               <chr> <chr> <chr> <chr> <chr> <chr> <chr>
 1 dolnośląskie        77,05 74,65 4,04  10,59 13,37 27,87 44,14
 2 kujawsko-pomorskie  78,12 65,93 4,29  14,96 14,82 27,01 38,92
 3 lubelskie           76,50 56,83 2,67  14,83 17,00 29,00 36,50
 4 lubuskie            79,10 76,23 4,92  12,70 12,70 30,74 38,93
 5 łódzkie             74,37 67,77 6,45  13,84 15,09 30,03 34,59
 6 małopolskie         72,71 55,35 6,99  14,63 12,01 25,87 40,50
 7 mazowieckie         76,31 68,52 5,89  12,11 12,30 27,03 42,67
 8 opolskie            79,55 54,65 4,83  10,04 17,47 26,02 41,64
 9 podkarpackie        75,10 47,32 7,57  14,86 18,29 25,31 33,98
10 podlaskie           74,18 68,00 5,82  10,55 17,09 32,36 34,18
11 pomorskie           76,57 74,96 5,71  12,74 13,76 26,65 41,14
12 śląskie             73,51 81,15 4,89  14,96 14,43 26,64 39,08
13 świętokrzyskie      74,45 56,51 4,91  14,00 14,74 27,27 39,07
14 warmińsko-mazurskie 75,91 63,22 5,62  13,59 18,48 29,53 32,79
15 wielkopolskie       72,66 62,71 3,62  14,37 14,77 29,45 37,79
16 zachodniopomorskie  74,26 73,21 8,44  13,71 11,60 24,89 41,35

Я также добавил (первую строку) заголовок каждой таблицы в качестве атрибута к data.frame:

> attr(tables_list[[1]], "caption")
[1] "Tabela 1.2.2: Struktura zapadalnosci rejestrowanej w zależności od płci, miejsca zamieszkania oraz grupy"

Сравните это с PDF:

enter image description here

Кажется, это работало хорошо, за исключением того, что имена столбцов пропали.Не уверен, что есть способ их сохранить, но он не был включен в ваш вопрос, так что, возможно, у вас уже есть решение?

0 голосов
/ 03 апреля 2019

Вы должны попробовать Rcrawler .

Кажется, что его основная функция Rcrawler разработана специально для ваших нужд - с аргументом KeywordsFilter:

KeywordsFilter  

символьного вектора, для пользователей, которые хотят очистить илисобирать только те веб-страницы, которые содержат несколько ключевых слов, одно или несколько.Rcrawler рассчитывает показатель точности на основе количества найденных ключевых слов.Этот параметр должен быть вектором по крайней мере с одним ключевым словом, например c ("mykeyword").

...