titulo - Cómo convertir datos de archivos pdf en marcos de datos
metadata pdf (1)
Aquí hay una posible solución usando expresiones regulares. Utiliza la función readPDF
del paquete tm
para convertir los archivos PDF a texto, dándole cada fila como una cadena de texto. Luego, utiliza expresiones regulares para dividir los datos en los campos de columna apropiados para la conversión a un marco de datos.
He empaquetado esto en una función para que pueda leer y analizar todos los archivos PDF y combinarlos en un único marco de datos en una sola operación. Si sus otros archivos tienen idiosincrasias de formato que no están presentes en el archivo que publicó, entonces deberá hacer algunos ajustes para que funcionen correctamente.
El código también verifica algunos problemas simples de formato de datos y guarda las filas "incorrectas" en un archivo de texto separado para su posterior inspección y procesamiento. Una vez más, puede necesitar modificar esto si sus otros archivos tienen variaciones de formato diferentes.
# Use text-mining package to extract text from PDF files
library(tm)
# Function to read a PDF file and turn it into a data frame
PDFtoDF = function(file) {
## Extract PDF text. Each line of PDF becomes one element of the string vector dat.
dat = readPDF(control=list(text="-layout"))(elem=list(uri=file),
language="en", id="id1")
dat = c(as.character(dat))
## Keep only those strings that contain the data we want.
## These are the ones that begin with a number.
dat = dat[grep("^ {0,2}[0-9]{1,3}", dat)]
## Create separators so we can turn strings into a data frame. We''ll use the
## pipe "|" as a separator.
# Add pipe after first number (the row number in the PDF file)
dat = gsub("^ ?([0-9]{1,3}) ?", "//1|", dat)
# Replace each instance of 2 or more spaces in a row with a pipe separator. This
# works because the company names have a single space between words, while data
# fields generally have more than one space between them.
# (We just need to first add an extra space in a few cases where there''s only one
# space between two data fields.)
dat = gsub("(, HVOL )","//1 ", dat)
dat = gsub(" {2,100}", "|", dat)
## Check for data format problems
# Identify rows without the right number of fields (there should
# be six pipe characters per row) and save them to a file for
# later inspection and processing (in this case row 11 of the PDF file is excluded))
excludeRows = lapply(gregexpr("//|", dat), function(x) length(x)) != 6
write(dat[excludeRows], "rowsToCheck.txt", append=TRUE)
# Remove the excluded rows from the string vector
dat = dat[!excludeRows]
## Convert string vector to data frame
dat = read.table(text=dat, sep="|", quote="", stringsAsFactors=FALSE)
names(dat) = c("RowNum", "Reference Entity", "Sub-Index", "CLIP",
"Reference Obligation", "CUSIP/ISIN", "Weighting")
return(dat)
}
# Create vector of names of files to read
files = list.files(pattern="CDX.*//.pdf")
# Read each file, convert it to a data frame, then rbind into single data frame
df = do.call("rbind", lapply(files, PDFtoDF))
# Sample of data frame output from your sample file
df
RowNum Reference Entity Sub-Index CLIP Reference Obligation CUSIP/ISIN Weighting
1 1 ACE Limited FIN 0A4848AC9 ACE-INAHldgs 8.875 15Aug29 00440EAC1 0.008
2 2 Aetna Inc. FIN 0A8985AC5 AET 6.625 15Jun36 BondCall 00817YAF5 0.008
3 3 Alcoa Inc. INDU, HVOL 014B98AD5 AA 5.72 23Feb19 013817AP6 0.008
Estoy tratando de convertir los datos de una gran cantidad de archivos PDF a marcos de datos en R. He estado convirtiendo los archivos PDF a archivos .txt usando read.fwf (), pero el problema es que el ancho de todos. los archivos txt no son lo mismo ¿Hay alguna manera de determinar el ancho de las columnas o hay alguna forma de usar una función que no sea read.fwf ()?
Tengo una gran cantidad de archivos para convertir y todos tienen diferentes formatos para empezar, por lo que encontrar el ancho de columna específico para cada archivo es cada vez más tedioso. ¿Existe alguna forma más eficiente de convertir datos de archivos PDF a marcos de datos en R?