#r #pdf #pdftools
#r #PDF #pdftools
Вопрос:
Я использую R для извлечения данных из PDF-файлов, и пока все идет хорошо. Я только что открыл новую партию PDF-файлов и увидел, что мне нужно выяснить, как учитывать пустые ячейки. Я не нашел способа сделать это, и у меня есть сотни страниц, которые мне нужно просмотреть.
Я включил некоторые примеры данных. Я не нашел способа прикрепить сюда PDF-файлы, и они нигде не публикуются в Интернете. Я сохранил df
как CSV, затем скопировал и вставил это в документ Word, который я сохранил как CSV для этого примера. Скриншот также прилагается.
library(pdftools)
library(tidyverse)
# Example data
df <- data.frame("rows" = c("row1", "row2", "row3", "row4", "row5", "row6", "row7", "row8", "row9", "row10"),
"col1" = c(1, 2, "", 4, 5, 6, 7, 8, 9, 10),
"col2" = c(1, 2, 3, 4, "", "", 7, 8, 9, ""),
"col3" = c(1, 2, "", 4, 5, 6, 7, 8, 9, 10),
"col4" = c(1, 2, 3, 4, 5, 6, 7, "", 9, 10),
"col5" = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
"col6" = c(1, 2, "", "", 5, 6, 7, "", 9, 10),
"col7" = c(1, 2, 3, 4, 5, "", 7, 8, 9, 10),
"col8" = c(1, "", 3, 4, 5, 6, 7, "", 9, 10),
"col9" = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
)
# Save example data, then save as a PDF outside of R.
# write_csv(df, "sample_data.csv")
# read in the PDF
pdf_file <- pdf_text("sample_data.pdf")
data <- pdf_file[1]
data <- trimws(data)
data <- strsplit(data, "rn")
data <- data[[1]]
data <- str_split_fixed(data, " {2,}", 10) ## I think this is the step that needs to change
data <- data.frame(data, stringsAsFactors = FALSE)
# Print out outs of the data for reference.
> data
X1 X2 X3 X4 X5 X6 X7 X8 X9 X10
1 rows col1 col2 col3 col4 col5 col6 col7 col8 col9
2 row1 1 1 1 1 1 1 1 1 1
3 row2 2 2 2 2 2 2 2 2
4 row3 3 3 3 3 3 3
5 row4 4 4 4 4 4 4 4 4
6 row5 5 5 5 5 5 5 5 5
7 row6 6 6 6 6 6 6 6
8 row7 7 7 7 7 7 7 7 7 7
9 row8 8 8 8 8 8 8
10 row9 9 9 9 9 9 9 9 9 9
11 row10 10 10 10 10 10 10 10 10
df
rows col1 col2 col3 col4 col5 col6 col7 col8 col9
1 row1 1 1 1 1 1 1 1 1 1
2 row2 2 2 2 2 2 2 2 2
3 row3 3 3 3 3 3 3
4 row4 4 4 4 4 4 4 4 4
5 row5 5 5 5 5 5 5 5 5
6 row6 6 6 6 6 6 6 6
7 row7 7 7 7 7 7 7 7 7 7
8 row8 8 8 8 8 8 8
9 row9 9 9 9 9 9 9 9 9 9
10 row10 10 10 10 10 10 10 10 10
ОБНОВЛЕНИЕ: добавление dput(pdf_file)
> dput(pdf_file)
"rows col1 col2 col3 col4 col5 col6 col7 col8 col9rnrow1 1 1 1 1 1 1 1 1 1rnrow2 2 2 2 2 2 2 2 2rnrow3 3 3 3 3 3 3rnrow4 4 4 4 4 4 4 4 4rnrow5 5 5 5 5 5 5 5 5rnrow6 6 6 6 6 6 6 6rnrow7 7 7 7 7 7 7 7 7 7rnrow8 8 8 8 8 8 8rnrow9 9 9 9 9 9 9 9 9 9rnrow10 10 10 10 10 10 10 10 10rn"
Вы можете видеть, что df
на этом этапе есть разница между data
и. Я попытался поиграть с несколькими вещами, и мне не удалось заставить что-либо работать достаточно хорошо, чтобы опубликовать здесь. Я попытался использовать некоторую логику if / else, чтобы сказать, что если есть 3 или более пробелов, вставьте NA, но это просто вызвало кучу ошибок, поэтому я отказался от этого подхода. Моя цель — получить данные как можно ближе к df.
Ответ №1:
Попробуйте использовать read.fwf
как файл фиксированной ширины.
data <- pdf_file[1]
data <- trimws(data)
data <- strsplit(data, "rn")
data <- data[[1]]
writeLines(data, 'temp.txt')
result <- read.fwf('temp.txt', c(11, 2, rep(8, 8)), skip = 1, strip.white = TRUE)
names(result) <- scan(text = readLines('temp.txt', n = 1), what = character())
result
# rows col1 col2 col3 col4 col5 col6 col7 col8 col9
#1 row1 1 1 1 1 1 1 1 1 1
#2 row2 2 2 2 2 2 2 2 NA 2
#3 row3 NA 3 NA 3 3 NA 3 3 3
#4 row4 4 4 4 4 4 NA 4 4 4
#5 row5 5 NA 5 5 5 5 5 5 5
#6 row6 6 NA 6 6 6 6 NA 6 6
#7 row7 7 7 7 7 7 7 7 7 7
#8 row8 8 8 8 NA 8 NA 8 NA 8
#9 row9 9 9 9 9 9 9 9 9 9
#10 row10 10 NA 10 10 10 10 10 10 10
Комментарии:
1. Спасибо. Это дает заголовки моих данных, но не помогает сохранить положение этих пустых ячеек в dataframe, что мне действительно нужно.
2. Yeah..It довольно сложно скорректировать ответ, когда у меня нет необходимых данных. Можете ли вы включить выходные
dput(pdf_file)
данные в свой пост @pkpto39?3. Да, я добавил это выше.
4. @pkpto39 Можете ли вы попробовать обновленный ответ, используя
read.fwf
, он сработал для меня.5. Спасибо. Потребовалось немного поиграть с шириной, но в конце концов я заставил это работать. Есть ли у вас какие-либо предложения по наилучшему определению ширины столбцов?
Ответ №2:
Это выглядит как хороший сценарий для использования tabulizer
пакета. Это работает очень хорошо, когда в PDF есть красиво отформатированные таблицы, подобные этой. Смотрите виньетку. Лучшей функцией здесь для вас было бы tabulizer::extract_tables
. Он также должен распознавать пробелы как пустые значения, предполагая, что все PDF-файлы хорошо отформатированы таким образом.
Комментарии:
1. К сожалению, не все данные отформатированы так хорошо, как это, и у меня были всевозможные проблемы с tabulizer. Это может быть вариантом для некоторых из них, поэтому я попробую.