Teoría

El reconocimiento óptico de caracteres (OCR) es una tecnología utilizada para convertir diferentes tipos de documentos (imágenes, documentos impresos escaneados, fotografías de texto, archivos PDF) en datos editables y buscables.

La Minería de Textos (TM) es el proceso de extraer información útil, patrones o conocimiento de texto no estructurado.

Consta de 3 etapas:

  1. Obtener datos: el OCR convierte imágenes de texto en texto editable.
  2. Explorar datos: representación visual para su interpretación (análisis de sentimientos, nube de palabras, topic modeling).
  3. Análisis predictivo: técnicas y modelos estadísticos para predecir resultados (random forest, redes neuronales, regresiones).

Instalar paquetes y llamar librerías

De imagen PNG a texto en Word

imagen1 <- image_read("/Users/brisnaordaz/Downloads/imagen1.PNG")
texto1  <- ocr(imagen1)

doc1 <- read_docx() %>%
  body_add_par(texto1)

print(doc1, target = "texto1.docx")

#De imagen PNG en Español a texto en Word

imagen2 <- image_read("/Users/brisnaordaz/Downloads/imagen2.PNG")
texto2  <- ocr(imagen2, engine = eng_spa)

doc2 <- read_docx() %>%
  body_add_par(texto2)

print(doc2, target = "texto2.docx")

#De PDF a PNG y a texto

png_files <- pdftools::pdf_convert(
  "/Users/brisnaordaz/Downloads/eso.pdf",
  format = "png", dpi = 300
)
## Converting page 1 to eso_1.png... done!
## Converting page 2 to eso_2.png... done!
# OCR de cada página -> vector de texto (uno por página)
texto_paginas <- purrr::map_chr(png_files, ~ ocr(.x, engine = eng_spa))

# Texto unificado
texto_pdf <- paste(texto_paginas, collapse = "\n\n")

#Guardar cada página OCR en Word

for (i in seq_along(texto_paginas)) {
  read_docx() %>%
    body_add_par(texto_paginas[i]) %>%
    print(target = sprintf("texto_eso_%d.docx", i))
}

#Análisis de Emociones y Sentimientos

# Tokens del texto completo
texto_palabras <- syuzhet::get_tokens(texto_pdf)

# Análisis NRC (diccionario español)
emociones <- syuzhet::get_nrc_sentiment(texto_palabras, language = "spanish")

barplot(
  colSums(prop.table(emociones[, 1:8])),
  main = "Distribución de emociones",
  ylab = "Proporción",
  col = rainbow(8),
  las = 2
)

#Nube de palabras

palabras <- texto_palabras
palabras <- tm::removeWords(
  palabras,
  c(stopwords("spanish"), "habia", "hacia", "casi")
)

set.seed(123)
wordcloud(
  words       = palabras,
  min.freq    = 2,
  rot.per     = 0,
  random.order = FALSE,
  colors      = brewer.pal(8, "Dark2")
)
## Warning in tm_map.SimpleCorpus(corpus, tm::removePunctuation): transformation
## drops documents
## Warning in tm_map.SimpleCorpus(corpus, function(x) tm::removeWords(x,
## tm::stopwords())): transformation drops documents

LS0tCnRpdGxlOiAiT0NSIgphdXRob3I6ICJBMDEyNzYwNDUgLSBCUklTTkEgRi4gT1JEQVogTU9OUk9ZIgpkYXRlOiAiMjAyNS0wOC0yMCIKZW5jb2Rpbmc6IFVURi04Cm91dHB1dDoKICBodG1sX2RvY3VtZW50OgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIGNvZGVfZG93bmxvYWQ6IHRydWUKICAgIHRoZW1lOiAiY29zbW8iCi0tLQoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5UZW9yw61hPC9zcGFuPgoKRWwgcmVjb25vY2ltaWVudG8gw7NwdGljbyBkZSAqKmNhcmFjdGVyZXMgKE9DUikqKiBlcyB1bmEgdGVjbm9sb2fDrWEgdXRpbGl6YWRhIHBhcmEgY29udmVydGlyIGRpZmVyZW50ZXMgdGlwb3MgZGUgKipkb2N1bWVudG9zKiogKGltw6FnZW5lcywgZG9jdW1lbnRvcyBpbXByZXNvcyBlc2NhbmVhZG9zLCBmb3RvZ3JhZsOtYXMgZGUgdGV4dG8sIGFyY2hpdm9zIFBERikgZW4gZGF0b3MgZWRpdGFibGVzIHkgYnVzY2FibGVzLgoKTGEgKipNaW5lcsOtYSBkZSBUZXh0b3MgKFRNKSoqIGVzIGVsIHByb2Nlc28gZGUgZXh0cmFlciBpbmZvcm1hY2nDs24gw7p0aWwsIHBhdHJvbmVzIG8gY29ub2NpbWllbnRvIGRlIHRleHRvIG5vIGVzdHJ1Y3R1cmFkby4KCkNvbnN0YSBkZSAzIGV0YXBhczoKCjEuICoqT2J0ZW5lciBkYXRvczoqKiBlbCBPQ1IgY29udmllcnRlIGltw6FnZW5lcyBkZSB0ZXh0byBlbiB0ZXh0byBlZGl0YWJsZS4gIAoyLiAqKkV4cGxvcmFyIGRhdG9zOioqIHJlcHJlc2VudGFjacOzbiB2aXN1YWwgcGFyYSBzdSBpbnRlcnByZXRhY2nDs24gKGFuw6FsaXNpcyBkZSBzZW50aW1pZW50b3MsIG51YmUgZGUgcGFsYWJyYXMsICp0b3BpYyBtb2RlbGluZyopLiAgCjMuICoqQW7DoWxpc2lzIHByZWRpY3Rpdm86KiogdMOpY25pY2FzIHkgbW9kZWxvcyBlc3RhZMOtc3RpY29zIHBhcmEgcHJlZGVjaXIgcmVzdWx0YWRvcyAocmFuZG9tIGZvcmVzdCwgcmVkZXMgbmV1cm9uYWxlcywgcmVncmVzaW9uZXMpLiAKCgojIDxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkluc3RhbGFyIHBhcXVldGVzIHkgbGxhbWFyIGxpYnJlcsOtYXM8L3NwYW4+CgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9Cm9wdGlvbnMoZW5jb2RpbmcgPSAiVVRGLTgiKQprbml0cjo6b3B0c19rbml0JHNldChlbmNvZGluZyA9ICJVVEYtOCIpCgpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeSh0ZXNzZXJhY3QpCmxpYnJhcnkobWFnaWNrKQpsaWJyYXJ5KG9mZmljZXIpCmxpYnJhcnkocGRmdG9vbHMpCmxpYnJhcnkocHVycnIpCmxpYnJhcnkoc3l1emhldCkKbGlicmFyeSh0bSkKbGlicmFyeSh3b3JkY2xvdWQpCmxpYnJhcnkoUkNvbG9yQnJld2VyKQoKIyBEZXNjYXJnYXIgaWRpb21hIGVzcGHDsW9sIHNvbG8gc2kgZmFsdGEKaWYgKCEic3BhIiAlaW4lIHRlc3NlcmFjdF9pbmZvKCkkYXZhaWxhYmxlKSB7CiAgdGVzc2VyYWN0X2Rvd25sb2FkKCJzcGEiKQp9CmVuZ19zcGEgPC0gdGVzc2VyYWN0KCJzcGEiKQoKYGBgCgoKIyA8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5EZSBpbWFnZW4gUE5HIGEgdGV4dG8gZW4gV29yZDwvc3Bhbj4KCmBgYHtyfQppbWFnZW4xIDwtIGltYWdlX3JlYWQoIi9Vc2Vycy9icmlzbmFvcmRhei9Eb3dubG9hZHMvaW1hZ2VuMS5QTkciKQp0ZXh0bzEgIDwtIG9jcihpbWFnZW4xKQoKZG9jMSA8LSByZWFkX2RvY3goKSAlPiUKICBib2R5X2FkZF9wYXIodGV4dG8xKQoKcHJpbnQoZG9jMSwgdGFyZ2V0ID0gInRleHRvMS5kb2N4IikKCmBgYAoKIzxzcGFuIHN0eWxlPSJjb2xvcjogYmx1ZTsiPkRlIGltYWdlbiBQTkcgZW4gRXNwYcOxb2wgYSB0ZXh0byBlbiBXb3JkPC9zcGFuPgoKYGBge3J9CmltYWdlbjIgPC0gaW1hZ2VfcmVhZCgiL1VzZXJzL2JyaXNuYW9yZGF6L0Rvd25sb2Fkcy9pbWFnZW4yLlBORyIpCnRleHRvMiAgPC0gb2NyKGltYWdlbjIsIGVuZ2luZSA9IGVuZ19zcGEpCgpkb2MyIDwtIHJlYWRfZG9jeCgpICU+JQogIGJvZHlfYWRkX3Bhcih0ZXh0bzIpCgpwcmludChkb2MyLCB0YXJnZXQgPSAidGV4dG8yLmRvY3giKQoKYGBgCgojPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+RGUgUERGIGEgUE5HIHkgYSB0ZXh0bzwvc3Bhbj4KYGBge3J9CnBuZ19maWxlcyA8LSBwZGZ0b29sczo6cGRmX2NvbnZlcnQoCiAgIi9Vc2Vycy9icmlzbmFvcmRhei9Eb3dubG9hZHMvZXNvLnBkZiIsCiAgZm9ybWF0ID0gInBuZyIsIGRwaSA9IDMwMAopCgojIE9DUiBkZSBjYWRhIHDDoWdpbmEgLT4gdmVjdG9yIGRlIHRleHRvICh1bm8gcG9yIHDDoWdpbmEpCnRleHRvX3BhZ2luYXMgPC0gcHVycnI6Om1hcF9jaHIocG5nX2ZpbGVzLCB+IG9jcigueCwgZW5naW5lID0gZW5nX3NwYSkpCgojIFRleHRvIHVuaWZpY2Fkbwp0ZXh0b19wZGYgPC0gcGFzdGUodGV4dG9fcGFnaW5hcywgY29sbGFwc2UgPSAiXG5cbiIpCgpgYGAKCiM8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5HdWFyZGFyIGNhZGEgcMOhZ2luYSBPQ1IgZW4gV29yZDwvc3Bhbj4KCmBgYHtyfQpmb3IgKGkgaW4gc2VxX2Fsb25nKHRleHRvX3BhZ2luYXMpKSB7CiAgcmVhZF9kb2N4KCkgJT4lCiAgICBib2R5X2FkZF9wYXIodGV4dG9fcGFnaW5hc1tpXSkgJT4lCiAgICBwcmludCh0YXJnZXQgPSBzcHJpbnRmKCJ0ZXh0b19lc29fJWQuZG9jeCIsIGkpKQp9CgpgYGAKCiM8c3BhbiBzdHlsZT0iY29sb3I6IGJsdWU7Ij5BbsOhbGlzaXMgZGUgRW1vY2lvbmVzIHkgU2VudGltaWVudG9zPC9zcGFuPgoKYGBge3J9CiMgVG9rZW5zIGRlbCB0ZXh0byBjb21wbGV0bwp0ZXh0b19wYWxhYnJhcyA8LSBzeXV6aGV0OjpnZXRfdG9rZW5zKHRleHRvX3BkZikKCiMgQW7DoWxpc2lzIE5SQyAoZGljY2lvbmFyaW8gZXNwYcOxb2wpCmVtb2Npb25lcyA8LSBzeXV6aGV0OjpnZXRfbnJjX3NlbnRpbWVudCh0ZXh0b19wYWxhYnJhcywgbGFuZ3VhZ2UgPSAic3BhbmlzaCIpCgpiYXJwbG90KAogIGNvbFN1bXMocHJvcC50YWJsZShlbW9jaW9uZXNbLCAxOjhdKSksCiAgbWFpbiA9ICJEaXN0cmlidWNpw7NuIGRlIGVtb2Npb25lcyIsCiAgeWxhYiA9ICJQcm9wb3JjacOzbiIsCiAgY29sID0gcmFpbmJvdyg4KSwKICBsYXMgPSAyCikKCmBgYAojPHNwYW4gc3R5bGU9ImNvbG9yOiBibHVlOyI+TnViZSBkZSBwYWxhYnJhczwvc3Bhbj4KYGBge3J9CnBhbGFicmFzIDwtIHRleHRvX3BhbGFicmFzCnBhbGFicmFzIDwtIHRtOjpyZW1vdmVXb3JkcygKICBwYWxhYnJhcywKICBjKHN0b3B3b3Jkcygic3BhbmlzaCIpLCAiaGFiaWEiLCAiaGFjaWEiLCAiY2FzaSIpCikKCnNldC5zZWVkKDEyMykKd29yZGNsb3VkKAogIHdvcmRzICAgICAgID0gcGFsYWJyYXMsCiAgbWluLmZyZXEgICAgPSAyLAogIHJvdC5wZXIgICAgID0gMCwKICByYW5kb20ub3JkZXIgPSBGQUxTRSwKICBjb2xvcnMgICAgICA9IGJyZXdlci5wYWwoOCwgIkRhcmsyIikKKQoKYGBgCgo=