En la entrada de hoy vamos a echarle un ojo a algunas herramientas para realizar análisis de texto utilizando R. Tal y como describe el titulo, este post es introductorio, por lo que se basa en la técnica ‘Bag of words’, es decir, no existe análisis semántico del texto, sino que se trabaja con palabras. 

Crearemos un Corpus con una colección de ficheros de texto plano, limpiaremos un poco el texto, y crearemos visualizaciones básicas, nos serviremos de los paquetes tm, qdap y wordcloud.

En la práctica, el modelo Bag of Words se usa principalmente como una herramienta de generación de atributos, o características a partir de un texto. Después de transformar el texto en una “bolsa de palabras”, podemos calcular varias medidas para caracterizarlo. El tipo más común de características, o características calculadas, a partir del modelo de Bag of Words, es la frecuencia de los términos, es decir, la cantidad de veces que aparece un término en el texto.

De forma general podemos identificar una serie de pasos a seguir:

  • Definir el problema u objetivo a resolver
  • Identificar el texto a utilizar en la resolución del problema
  • Organizar el texto
  • Extraer características
  • Analizar los resultados para obtener respuestas al problema planteado.

Los dos primeros puntos quedan para la necesidad de cada uno, así que con un texto seleccionado sin atender a ningún criterio concreto nos ponemos manos a la obra.

En un directorio tenemos una colección de obras de William Shakespeare en formato .txt, con esta colección de documentos crearemos nuestro Corpus.

library(tm)
library(qdap)
library(wordcloud)

#Load into a VCorpus object the collection of documents from a Directory (DirSource) 
txt <- "C:/R Blog/"
shakespeare_corpus <- VCorpus(DirSource(txt, encoding = "UTF-8"), readerControl = list(language = "en"))

inspect(shakespeare_corpus[1:3])
shakespeare_corpus[[2]]$meta

VCorpus crea un corpus en memoria, hay que pasarle el ‘origen’ o ‘fuente’ (source) de los documentos que formarán la colección, en este caso se trata de un directorio ‘DirSource’ con una colección de txt’s, pero podría ser un vector, un dataframe o un XML entre otros.

Vamos a limpiar un poco el texto, para ello tenemos una función que llama a varias funciones de los paquetes qdap y tm.

#------------------------------Clean Corpora function-------------------------
clean_corpus <- function(corpus){
  corpus <- tm_map(corpus, stripWhitespace)
  corpus <- tm_map(corpus, removePunctuation)
  corpus <- tm_map(corpus, content_transformer(tolower))
  corpus <- tm_map(corpus, content_transformer(replace_abbreviation))
  corpus <- tm_map(corpus, removeNumbers)
  corpus <- tm_map(corpus, removeWords, c(stopwords("en"), "shall"
                                          ,"will", "let","thou", "thy", "shall", "thee", "will", "o"))
  return(corpus)
}
#-----------------------------------------------------------------------------

Un repaso de funciones útiles para limpiar el texto:

R base y tm:

  • tolower(): Pasamos todo a minúsculas (Cuidado si se buscan nombre propios) (R base)
  • removePunctuation(): Elimina puntuación (paquete tm)
  • removeNumbers(): Elimina numeros  (cuidado si se buscan cantindades) (paquete tm)
  • stripWhitespace(): Quita espacios extra (paquete tm)
  • removeWords(): Elimina palabras, muy útil combinarla con stopwords() (paquete tm)

 

Paquete qdap:

  • bracketX(): Elimina lo que esté entre paréntesis.
  • replace_number(): Pasa los numeros a palabras (por ejemplo. “2” pasa a “two”, tener en cuenta que el ejemplo se utiliza ingles)
  • replace_abbreviation(): camba abreviaciones por la versión completa  (por ejemplo “Sr” pasa a “Senior”)
  • replace_contraction(): Elimina contracciones (por ejemplo “can’t” pasa “can not”)
  • replace_symbol() Pasa símbolos a palabras (por ejemplo “@” pasa a “at”)

De la función para limpiar el corpus de arriba quizas lo mas interesante a destacar es eliminar las palabras comunes con removeWords(). Algunas líneas más adelante veremos la importancia de limpiar términos que no aportan información útil.

Vamos a obtener la frecuencia con la que aparecen los términos en la colección de documentos que tenemos, para ellos seguiremos los siguientes pasos:

  • Creamos una matriz de términos por documentos con TermDocumentMatrix() de tm.
  • La transformamos en matriz as.matrix.
  • Sumamos por filas para obtener el número de veces que aparece cada término.

Creamos una matriz de términos por documento, (Term-Document Matrix).

#Create a Term Document Matrix
shakespeare_tdm <- TermDocumentMatrix(shakespeare_corpus)

Si echamos un ojo en la consola al elemento que acabamos de crear vemos lo siguiente:

Introducción al Text Mining con R: Parte I

Vemos algunos datos sobre la naturaleza de nuestro texto, numero de términos, sparsity (espaciamiento o dispersión de los datos, nos describe en qué grado hay términos que se repiten entre documentos), término más largo, etc, también vemos una previsualización de la matriz, que nos representa la frecuencia de aparición de un término por cada documento.

Vamos a convertir la TDM a una matriz, de forma que sumaremos por filas para obtener la frecuencia de los términos sin tener en cuenta de que documento vienen, esto lo dejamos en un dataframe.

#Convert the tdm into a matrix
shakespeare_m <- as.matrix(shakespeare_tdm)

#sum rows to get frequency
shakespeare_words <- sort(rowSums(shakespeare_m), decreasing = T)   

#convert the matrix into a DF to get names and frequencies
shakespeare_freq <- data.frame(terms = names(shakespeare_words), num = shakespeare_words)

Se inspeccionamos el dataframe:

Introducción al Text Mining con R: Parte I

Ya tenemos el texto preparado para crear visualizaciones que nos ayuden a obtener conclusiones, crearemos una nube de palabras para empezar.

library(wordcloud)
#Create a wordcloud with the most 100 frequent terms
wordcloud(shakespeare_freq$term, shakespeare_freq$num, max.words = 100, colors = c( "grey", "orange", "red"))

Introducción al Text Mining con R: Parte I

Muy bien, ya tenemos nuestra primera wordcloud, volvamos a hablar de la importancia de limpiar el texto. Antes hicimos hincapié en removeWords() y en stopwords(“en”). Veamos el resultado si hubiésemos pasado esto por alto.

Introducción al Text Mining con R: Parte I

Oooops! no parece demasiado útil el resultado de la derecha, ¿verdad?. Parece algo obvio a tener en cuenta, pero una imagen vale más que mil palabras, y lo interesante es que stopwords() nos da parte del trabajo listo. 

> stopwords("en")
  [1] "i"          "me"         "my"         "myself"     "we"         "our"        "ours"       "ourselves"  "you"       
 [10] "your"       "yours"      "yourself"   "yourselves" "he"         "him"        "his"        "himself"    "she"       
 [19] "her"        "hers"       "herself"    "it"         "its"        "itself"     "they"       "them"       "their"     
 [28] "theirs"     "themselves" "what"       "which"      "who"        "whom"       "this"       "that"       "these"     
 [37] "those"      "am"         "is"         "are"        "was"        "were"       "be"         "been"       "being"     
 [46] "have"       "has"        "had"        "having"     "do"         "does"       "did"        "doing"      "would"     
 [55] "should"     "could"      "ought"      "i'm"        "you're"     "he's"       "she's"      "it's"       "we're"     
 [64] "they're"    "i've"       "you've"     "we've"      "they've"    "i'd"        "you'd"      "he'd"       "she'd"     
 [73] "we'd"       "they'd"     "i'll"       "you'll"     "he'll"      "she'll"     "we'll"      "they'll"    "isn't"     
 [82] "aren't"     "wasn't"     "weren't"    "hasn't"     "haven't"    "hadn't"     "doesn't"    "don't"      "didn't"    
 [91] "won't"      "wouldn't"   "shan't"     "shouldn't"  "can't"      "cannot"     "couldn't"   "mustn't"    "let's"     
[100] "that's"     "who's"      "what's"     "here's"     "there's"    "when's"     "where's"    "why's"      "how's"     
[109] "a"          "an"         "the"        "and"        "but"        "if"         "or"         "because"    "as"        
[118] "until"      "while"      "of"         "at"         "by"         "for"        "with"       "about"      "against"   
[127] "between"    "into"       "through"    "during"     "before"     "after"      "above"      "below"      "to"        
[136] "from"       "up"         "down"       "in"         "out"        "on"         "off"        "over"       "under"     
[145] "again"      "further"    "then"       "once"       "here"       "there"      "when"       "where"      "why"       
[154] "how"        "all"        "any"        "both"       "each"       "few"        "more"       "most"       "other"     
[163] "some"       "such"       "no"         "nor"        "not"        "only"       "own"        "same"       "so"        
[172] "than"       "too"        "very"

SI revisamos la función de limpieza del Corpus más arriba veremos que a stopwords(“en”) se le concatena un vector con una serie de palabras en ingles antiguo, estas palabras se añadieron al ver que contaminaban el resultado, pero como siempre, esto depende del resultado que se esté buscando.

¿Quieres conocer más sobre el text mining? Te recomiendo la segunda parte de este artículo, donde explico otras visualizaciones útiles y consideraciones útiles sobre el texto a analizar.

0 Shares:
5 comments
  1. Hola Guillermo,

    Parece que eres un experto en analisis de textos. sabes si es posible preprocesar el texto con tm (limpiar simbolos, numeros, stopwords, etc, etc.) y luego pasarlo a quanteda para creat un dtm? Como se realiza ese pasaje? Esto que busco ejemplos y no encuentro.

    1. Hola Ruben, lo primero ‘Experto’ son palabras mayores, pero gracias 🙂

      Como te comenté por mail, Quanteda acepta VCorpus para crear un corpus de Quanteda, y de ahí en adelante ya lo que veas…

      ej:

      tm_vcorpus <- VCorpus()
      quanteda_corpus <- corpus(tm_vcorpus)

      luego la 'document-feature matrix'

      quanteda_dfm <- dfm(quanteda_corpus)

      fuente: https://tutorials.quanteda.io/basic-operations/

      Espero te sea de ayuda.

      Saludos

  2. Perdone la data que utilizan de obras de las obras de William Shakespeare en formato .txt donde la puedo descargar para realizar este ejercicio.

  3. Hola Guillermo,

    Como pedo aplicar esta función o análisis para una columna que contenga textos y no un archivo de texto.

    Gracias. ?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

You May Also Like