R - Экспорт извлеченных текстовых данных (каждый экземпляр как строка) в формат data.frame - PullRequest
1 голос
/ 10 марта 2020

Я пытаюсь извлечь / экспортировать текст из числа стандартизированных экземпляров из числа стандартизированных форм .txt во фрейм данных, где каждый экземпляр представляет собой отдельную строку. Затем я хочу экспортировать эти данные в виде файла .xlsx. До сих пор я могу успешно извлечь данные (хотя алгоритм извлекает немного больше, чем заявленные параметры gregexpr ()), но может экспортировать только как .txt в виде единовременной суммы текста.

  1. Как создать фрейм данных из текста извлеченных текстовых файлов, где каждый экземпляр имеет свою собственную строку? (Как только данные в формате data.frame, я знаю, как оттуда экспортировать как xlsx.)
  2. Как извлечь только данные из параметров, которые я установил?

С помощью (в частности, из Бена из комментариев к этому посту ), вот что у меня есть до сих пор:

# Txt Data Format
txt 1 <-
"A. The First:  abcdefg hijklmnop qrstuv wxyz.
 B. The Second: abcdefg hijklmnop qrstuv wxyz.
 C. The Third:  abcdefg hijklmnop qrstuv wxyz.
 D. The Fourth: abcdefg hijklmnop qrstuv wxyz.

 A. The First:  abcdefg hijklmnop qrstuv wxyz.
 B. The Second: abcdefg hijklmnop qrstuv wxyz.
 C. The Third:  abcdefg hijklmnop qrstuv wxyz.
 D. The Fourth: abcdefg hijklmnop qrstuv wxyz."

txt 2 <-
"A. The First:  abcdefg hijklmnop qrstuv wxyz.
 B. The Second: abcdefg hijklmnop qrstuv wxyz.
 C. The Third:  abcdefg hijklmnop qrstuv wxyz.
 D. The Fourth: abcdefg hijklmnop qrstuv wxyz.

 A. The First:  abcdefg hijklmnop qrstuv wxyz.
 B. The Second: abcdefg hijklmnop qrstuv wxyz.
 C. The Third:  abcdefg hijklmnop qrstuv wxyz.
 D. The Fourth: abcdefg hijklmnop qrstuv wxyz."


#################################
# Directory and Text Extraction #
#################################

dest <- "C:/Desktop/"
docs_text <- list.files(path = dest, pattern = "txt",  full.names = TRUE)

## Assumes that all the content I want to extract is between "A." and "C." in 
## the text while ignoring "C." and "D." content.

docs_list <- list.files(path = dest, pattern = "txt",  full.names = TRUE)
docs_doc <- lapply(docs_list, function(i) {
  j <- paste0(scan(i, what = character()), collapse = " ")
  regmatches(j, gregexpr("(?<=A. The First).*?(?=C. The Third)", j, perl=TRUE))
})

lapply(1:length(docs_doc),  function(i) write.table(docs_doc[i], file=paste(docs_list[i], " ", 
" ", sep="."), quote = FALSE, row.names = FALSE, col.names = FALSE, eol = " " ))

Текущий вывод выглядит так, где весь текст в одну строку и захватывает больше, чем просто между "А." и "C.":

Current Output

Желаемый результат будет выглядеть так, когда несколько строк текста только между "A." и "C." и каждый многострочный захват назначается по одной строке для каждого экземпляра:

Desired Output

Любая помощь, которую вы могли бы оказать, была бы чрезвычайно полезной!

В конечном итоге я пытаюсь разработать модель НЛП, которая могла бы извлекать стандартизированные данные форм из сотен больших PDF-файлов для годового хранилища. Если этот пост предполагает, что я не думаю о том, как подойти к этой проблеме эффективно / действенно, я открыт для направления.

Заранее спасибо!

1 Ответ

1 голос
/ 11 марта 2020

Я использую dplyr для удобства объекта tibble и очень эффективной команды bind_rows:

dest <- "~"
docs_text <- list.files(path = dest, pattern = "txt",  full.names = TRUE)

library(dplyr)

docs_df <- lapply(docs_text, function(f) {
  lines <- readLines(f)
  tibble(
    file = basename(f),
    line = seq_along(lines),
    text = lines
  )
  }) %>% 
  bind_rows()

Как только у вас есть правильный data.frame, его легко установить на подмножество используя filter и grepl, чтобы найти соответствующий текст. Я использую регулярное выражение "^A.|^B.", которое ищет строки, начинающиеся с A. или B.:

docs_df %>% 
  filter(grepl("^A.|^B.", text))
#> # A tibble: 8 x 3
#>   file       line text                                         
#>   <chr>     <int> <chr>                                        
#> 1 txt_1.txt     1 A. The First:  abcdefg hijklmnop qrstuv wxyz.
#> 2 txt_1.txt     2 B. The Second: abcdefg hijklmnop qrstuv wxyz.
#> 3 txt_1.txt     6 A. The First:  abcdefg hijklmnop qrstuv wxyz.
#> 4 txt_1.txt     7 B. The Second: abcdefg hijklmnop qrstuv wxyz.
#> 5 txt_2.txt     1 A. The First:  abcdefg hijklmnop qrstuv wxyz.
#> 6 txt_2.txt     2 B. The Second: abcdefg hijklmnop qrstuv wxyz.
#> 7 txt_2.txt     6 A. The First:  abcdefg hijklmnop qrstuv wxyz.
#> 8 txt_2.txt     7 B. The Second: abcdefg hijklmnop qrstuv wxyz.

Для экспорта в Excel я рекомендую rio::export().

...