Title
Vamos a ver una introducción a la minería de textos en R utilizando el texto de El Quijote.
Importación y manipulación
- Necesitamos descargar el texto de Project Gutenberg. Contiene las dos partes.
quijote_ruta <- "http://www.gutenberg.org/cache/epub/2000/pg2000.txt"
download.file(quijote_path, "quijote.txt")
# Especificamos el argumento encoding por los acentos y caracteres especiales como la ñ.
lineas <- readLines("quijote.txt", encoding = "UTF-8")
head(lineas, 3)
tail(lineas, 3)
- Observamos que hay texto no perteneciente al libro tanto al comienzo como al final.
head(lineas, 3)
[1] "The Project Gutenberg EBook of Don Quijote, by Miguel de Cervantes Saavedra"
[2] ""
[3] "This eBook is for the use of anyone anywhere at no cost and with"
tail(lineas, 3)
[1] "including how to make donations to the Project Gutenberg Literary"
[2] "Archive Foundation, how to help produce our new eBooks, and how to"
[3] "subscribe to our email newsletter to hear about new eBooks."
Lo eliminamos:
lineas <- lineas[-(1:36)] # Comienzo
lineas <- lineas[-(37454:length(lineas))] # Final
head(lineas, 3)
[1] "El ingenioso hidalgo don Quijote de la Mancha" ""
[3] ""
tail(lineas, 3)
[1] "" "" "Fin"
- Creamos el corpus. Utilizamos el paquete tm
library(tm)
doc.corpus <- Corpus(VectorSource(lineas))
[1] "El ingenioso hidalgo don Quijote de la Mancha" ""
[3] ""
- Realizamos varias transformaciones al texto
# Muestra las transformaciones disponibles
getTransformations()
# Realizaremos las siguientes:
doc.corpus <- tm_map(doc.corpus, content_transformer(tolower)) # Minúsculas
doc.corpus <- tm_map(doc.corpus, removePunctuation) # Puntuación
doc.corpus <- tm_map(doc.corpus, removeNumbers) # Números
- Construimos nuestro Term Document Matrix (TDM)
TDM <- TermDocumentMatrix(doc.corpus)
Con el argumento control controlamos la longitud de las palabras incluidas. Por defecto es c(3, Inf), es decir, palabras de más de 3 letras. Para incluir todas las palabras:
TDM <- TermDocumentMatrix(doc.corpus,
control = list(wordLengths = c(1, Inf)))
Consultas a nuestro corpus
- Inspección del corpus
inspect(TDM)
TermDocumentMatrix (terms: 22858, documents: 37453)
Non-/sparse entries: 253654/855847020
Sparsity : 100%
Maximal term length: 21
Weighting : term frequency (tf)
- Número de términos
dim(TDM)
[1] 22858 37453
- Términos frecuentes
Empleamos la función findFreqTerms(x, lowfreq = 0, highfreq = Inf). Por defecto el límite inferior es cero y el superior infinito.
# Más de 1.500 veces
palabras.frec <- findFreqTerms(TDM, 1500)
[1] "como" "con" "del" "dijo" "don" "las" "los" "más" "por" "que" "quijote" "sancho"
# Entre 100 y 1000
palabras.frec <- findFreqTerms(TDM, 100, 1000)
head(palabras.frec)
[1] "adelante" "agora" "ahora" "algo" "algún" "alguna"
- Asociaciones de palabras
Con la función findAssocs(x, terms, corlimit). Especificamos como corlimit cero, para que nos devuelva todas las palabras aunque la correlación sea mínima.
asociaciones <- findAssocs(TDM, "rocinante", 0)
head(asociaciones, 10)
rocinante
riendas 0.13
espuelas 0.12
picó 0.11
rucio 0.11
ayudándole 0.10
ensilló 0.10
huellas 0.10
cabestro 0.09
subió 0.09
Reducción del tamaño del corpus
EL tamaño de nuestra Term-Document Matrix (TDM) es a veces demasiado grande. Si deseamos reducirlo:
TDM.comun <- removeSparseTerms(TDM, 0.999)
dim(TDM.comun)
Cuanto más pequeño el
sparse factor, porcentaje aplicado —0.999 en nuestro ejemplo—, menor número de palabras (aquellas más frecuentes incluirá). En nuestro ejemplo como solamente tenemos un documento y nuestra sparsity es 100% (ver inspect(TDM)), para no eliminar todos los términos debemos especificar un porcentaje muy grande.
[1] 922 37453
Una manera de reducir drásticamente el tamaño de nuestro futuro corpus, es la siguiente línea:
doc.corpus <- Corpus(VectorSource(paste(lineas, collapse = " ")))
N-grams
Un n-gram es una secuencia continua de n elementos de un texto o discurso dado.
library(tau)
# Bigramas: n = 2
bigramas <- textcnt(lineas, n = 2, method = "string")
bigramas <- bigramas[order(bigramas, decreasing = TRUE)]
bigramas[1]
don quijote
2166
# n = 5
n5<- textcnt(lineas, n = 5, method = "string")
n5<- n5[order(n5, decreasing = TRUE)]
data.frame(n5 = n5[1:10])
n5
don quijote de la mancha 134
caballero de la triste figura 34
la señora dulcinea del toboso 24
el caballero de la triste 21
el cura y el barbero 21
en todos los días de 21
caballero don quijote de la 17
de don quijote de la 17
el duque y la duquesa 17
señor don quijote de la 16
# n = 10
n10 <- textcnt(lineas, n = 10, method = "string")
n10 <- n10[order(n10, decreasing = TRUE)]
data.frame(n10 = n10[1:10])
n10
cruel vireno fugitivo eneas barrabás te acompañe allá te avengas 4
parte del ingenioso hidalgo don quijote de la mancha capítulo 4
eso haré yo de muy buena gana señor mío respondió 3
parte de la historia de don quijote de la mancha 3
que desnudo nací desnudo me hallo ni pierdo ni gano 3
vuestro hasta la muerte el caballero de la triste figura 3
a dios rogando y con el mazo dando y que 2
a la sin par dulcinea del toboso única señora de 2
a mi casa y a mi mujer y a mis 2
antes se ha de perder por carta de más que 2
Exportación
Para exportar los resultados transformamos nuestro Term-Document Matrix (TDM) bien en una matriz o en un data frame.
m <- as.matrix(TDM) # Large matrix
Matriz
# Matriz
m1 <- sort(rowSums(m), decreasing = TRUE)
data.frame(frec = m1[1:10])# para mostrarlo en una columna
frec
que 20626
los 4748
con 4202
por 3940
las 3468
don 2647
del 2491
como 2263
quijote 2175
sancho 2148
# Exportamos la matriz
write.csv2(x = m1, file = "quijote89.csv", row.names = TRUE)
Data frame
# Data frame
df <- data.frame(ocurrencias = sort(rowSums(m), decreasing = TRUE))
write.csv2(x = df, file = "quijote.csv", row.names = TRUE)
Para consultar la
frecuencia de una palabra en nuestro data frame.
v["toledo", ]
[1] 11
Nube de palabras
Creamos una nube de palabras a partir de la matriz creada.
library(wordcloud)
set.seed(4) # Para obtener el mismo resultado siempre
wordcloud(rownames(m), rowSums(m), min.freq = 1000)
Referencias