Comprendamos primeramente que es el análisis de texto.
El análisis de texto es un proceso de fragmentación de párrafos o comunicaciones escritas, en oraciones y en palabras, a partir de un separador definido, por ejemplo, un espacio. Con el fin de medir frecuencias de palabras, relaciones entre ellas o los sentimientos que evocan cada palabra.
veamos un breve ejemplo de lo dicho anteriormente:
library(tidyverse)
library(tidytext)
wd= "C:/Users/danie/OneDrive/Escritorio/Laboratorio I"
setwd(wd)
discurso <- read_lines("texto.txt", skip = 4)
mensaje <- tibble (parrafo= seq_along(discurso),
texto = discurso)
## # A tibble: 1,230 × 2
## parrafo texto
## <int> <chr>
## 1 1 ########## FIN ENCABEZADO ##########
## 2 2 – I –
## 3 3 En Marzo de 1808, y cuando habían transcurrido cuatro meses desde qu…
## 4 4 Mi vida al principio era tan triste y tan uniforme como aquel oficio…
## 5 5 Necesito explicarme mejor. Yo pensaba en la huérfana Inés, y todos l…
## 6 6 –Mi amiga está en Aranjuez con su reverendo tío, el padre D. Celesti…
## 7 7 Cuando no me ocupaba en estas alabanzas, departía mentalmente con el…
## 8 8 ¡Aquellos pensamientos y este mecanismo todas las horas, todos los d…
## 9 9 Pero la alegría no estaba sino en el alma. El sábado es el precursor…
## 10 10 Con voluble atención observo todos los accidentes del camino, y mis …
## # … with 1,220 more rows
Para este caso, utilizaremos dos librerias muy conocidas para la mineria de texto llamadas tidyverse() y tidytex(), seguidamente establecemos un directorio de trabajo y usaremos un texto de ejemplo (“texto”), dividimos un texto en parrafos con la función tibble, a lo que finalmente le haremos el proceso de tokenizacion para cada palabra del corpus
realizando nuestro proceso de tokenizacion tenemos que tener encuenta algunos factores importantes, como lo son las mayusculas y algunos signos de puntuación dado que R puede llegar a todar la “A” y la “a” como tokens diferentes dificultando todo el proceso de análisis
mensaje_palabras <- mensaje %>% unnest_tokens(palabra, texto)
mensaje %>%
unnest_tokens(palabra,
texto,
to_lower = FALSE)
## # A tibble: 67,863 × 2
## parrafo palabra
## <int> <chr>
## 1 1 FIN
## 2 1 ENCABEZADO
## 3 2 I
## 4 3 En
## 5 3 Marzo
## 6 3 de
## 7 3 1808
## 8 3 y
## 9 3 cuando
## 10 3 habían
## # … with 67,853 more rows
En este caso vemos como cada palabra ya fue dividida recuerden que, con la función unnest_tokens() le estás ordenando que extraiga todas y cada una de las palabras que conforman el texto que hay almacenado en mensaje y que las guarde en la columna palabra de la nueva tabla que le has dicho que se llamará mensaje_palabras
la frecuencia con la que se repiten algunas palabras pueden ser muy utiles para nuestos análisis, con nuestro anterior ejemplo tenemos de mayor a menor, en la primera colmuna la palabra en cuestión y en la segunda colmuna la cantidad con que esta se repite, para este ejemplo las palabras que mas se repiten logicamente son conectores, sin embargo estos no son muy utiles para el análisis, por lo que posteriormente mostraremos como depurarlos.
mensaje_palabras %>%
count(palabra,
sort = TRUE)
## # A tibble: 10,705 × 2
## palabra n
## <chr> <int>
## 1 de 3491
## 2 que 2454
## 3 la 2290
## 4 y 2196
## 5 a 1668
## 6 el 1420
## 7 en 1406
## 8 no 1156
## 9 los 971
## 10 se 795
## # … with 10,695 more rows
Para este segundo ejemplo usaremos las siguientes librerias las cuales se usaran más que todo para la grafiación de nuestro análisis.
library(tm)
library(SnowballC)
library(RColorBrewer)
library(wordcloud)
library(ggplot2)
library(dplyr)
library(readr)
library(cluster)
Establecemos nuevamente la ruta de trabajo para prepara nuestro texto (“quince”) denominado corpus.
wd= "C:/Users/danie/OneDrive/Escritorio/Laboratorio I"
setwd(wd)
nov_raw <- read_lines("quince.txt") #n_max, skip
str(nov_raw)
## chr [1:313] "Cuento de Charles Bukowski: Quince centímetros" ...
para este ejemplo el texto lo que haremos es ampliar los parrafos del texto para 10 repeticiones, lo usaremos para que el grupo sea de 10 reglones cada uno de estos parrafos seran vectores que posteriormente usaremos para unirlo con nuestro texto.
diez <- rep(1:ceiling(length(nov_raw)/10), each = 10) # para hacer gurpos de 10 reglones
diez <- diez[1:length(nov_raw)]
nov_text <- cbind(diez, nov_raw) %>% data.frame()
Ahora pues, concatenaremos los reglones con la función aggregate donde finalmente obtenemos una matriz de 32x1
formula = nov_raw ~ diez
nov_text <- aggregate(formula,
data = nov_text,
FUN = paste,
collapse = " ")
nov_text <- nov_text %>% select(nov_raw) %>% as.matrix
dim(nov_text)
## [1] 32 1
Una vez realizado nuestro proceso de tokenizacion procedemos a limpiar o depurar caracteres especiales, muletillas, puntuación y espacios vacios excesivos.
nov_text <- gsub("[[:cntrl:]]", " ", nov_text) #eliminar caracteresespeciales
nov_text <- tolower(nov_text) # convertir el texto en minusculas
nov_text <- removeWords(nov_text, words = stopwords("spanish")) # para eliminar preposicion y muletillas
nov_text <- removePunctuation(nov_text) # elimina la puntuacion
nov_text <- stripWhitespace(nov_text) # eliminamos espacios vacios excesivos
Análisando nuestro corpus podemos ver que esta compuesto por 32 documentos
nov_corpus <- Corpus(VectorSource(nov_text))
nov_corpus
## <<SimpleCorpus>>
## Metadata: corpus specific: 1, document level (indexed): 0
## Content: documents: 32
las siguientes graficas son apartir del corpus.
wordcloud(nov_corpus,
max.words = 80, random.order = F, colors = brewer.pal(name = "Dark2", n = 8))
Con este tipo de grafico podemos observar que, las palabras más grandes son las que más se repiten, en nuestra historia podemos observar como Sara es nuestra protagonista.
Algunas palabras como algunos conectores que aparecen en el anterior grafico no son de mucha utilidad por lo que depuraremos estas para acercarnos un poco más a un mejor análsis.
nov_text <- removeWords(nov_text, words = c( "dijo", "tan", "después", "aquel", "así", "aún", "sino", "entonces", "aunque"))
nov_corpus <- nov_text %>% VectorSource() %>% Corpus()
nov_ptd <- nov_corpus %>% tm_map(PlainTextDocument)
wordcloud(
nov_corpus, max.words = 80,
random.order = F,
colors=brewer.pal(name = "Dark2", n = 8)
)
Con esto podemos observar un breve resumen del texto.
nov_tdm <- TermDocumentMatrix(nov_corpus) # asociacion entre palabras
nov_tdm
## <<TermDocumentMatrix (terms: 1128, documents: 32)>>
## Non-/sparse entries: 1674/34422
## Sparsity : 95%
## Maximal term length: 17
## Weighting : term frequency (tf)
Veamos pues para este ejemplo la frecuencia con la que son usadas algunas palabras
nov_mat <- as.matrix(nov_tdm)
dim(nov_mat)
## [1] 1128 32
nov_mat <- nov_mat %>% rowSums() %>% sort(decreasing = TRUE)
nov_mat <- data.frame(palabra = names(nov_mat), frec = nov_mat)
nov_mat[1:20,]
## palabra frec
## — — 46
## sara sara 32
## luego luego 21
## cerveza cerveza 15
## centímetros centímetros 14
## vez vez 14
## —¿ —¿ 12
## noche noche 12
## alfiler alfiler 11
## allí allí 9
## empezó empezó 9
## harry harry 9
## cada cada 9
## podía podía 8
## quince quince 8
## veces veces 8
## cabeza cabeza 8
## hacia hacia 8
## bien bien 7
## hacer hacer 7
Adicionalmente grafiquemos la frecuencia de esto solo usaremos las 10 palabras con más frecuencia.
nov_mat[1:10, ] %>%
ggplot(aes(palabra, frec)) +
geom_bar(stat = "identity", color = "black", fill = "#FFBA61") +
geom_text(aes(hjust = 1.3, label = frec)) +
coord_flip() +
labs(title = "Diez palabras más frecuentes", x = "Palabras", y = "Número de usos")
nov_mat %>%
mutate(perc = (frec/sum(frec))*100) %>%
.[1:10, ] %>%
ggplot(aes(palabra, perc)) +
geom_bar(stat = "identity", color = "black", fill = "#FFBA61") +
geom_text(aes(hjust = 1.3, label = round(perc, 2))) +
coord_flip() +
labs(title = "Diez palabras más frecuentes", x = "Palabras", y = "Porcentaje de uso")
Estas asociaciones nos pertimirar ver la relación que tienen algunas palabras con otras podemos buscar una palabra especifica a la cual queremos ver su asociacion.
findAssocs(nov_tdm, terms = c( "sara", "hombre"), corlimit = .60)
## $sara
## apenas
## 0.71
##
## $hombre
## parte abiertas acabase adelante aproximaba
## 0.68 0.66 0.66 0.66 0.66
## aquella arderme arqueaba arremetía atrás
## 0.66 0.66 0.66 0.66 0.66
## barca bolsitas bosque capas cerveza—
## 0.66 0.66 0.66 0.66 0.66
## cuerpo curvo dedos dentro… despacio
## 0.66 0.66 0.66 0.66 0.66
## espalda gancho gemido gemir insoportable
## 0.66 0.66 0.66 0.66 0.66
## jadeos lanzaba llénalo monín moverme
## 0.66 0.66 0.66 0.66 0.66
## oscuridad oxígeno oía pegaba pelos
## 0.66 0.66 0.66 0.66 0.66
## peste piernas poquito posible presintiendo
## 0.66 0.66 0.66 0.66 0.66
## puse realidad repugnante respirar rígido
## 0.66 0.66 0.66 0.66 0.66
## sufriría superiluminado superior terrible verdaderamente
## 0.66 0.66 0.66 0.66 0.66
## —saborea cosa
## 0.66 0.64
eliminamos terminos dispersos para tener mas claridad en nuestro analisis y compararmos
nov_new <- removeSparseTerms(nov_tdm, sparse = .85)
#texto anterior
nov_tdm
## <<TermDocumentMatrix (terms: 1128, documents: 32)>>
## Non-/sparse entries: 1674/34422
## Sparsity : 95%
## Maximal term length: 17
## Weighting : term frequency (tf)
#texto nuevo
nov_new
## <<TermDocumentMatrix (terms: 28, documents: 32)>>
## Non-/sparse entries: 211/685
## Sparsity : 76%
## Maximal term length: 11
## Weighting : term frequency (tf)
vemos como pasamos de tener 1128 terminos a 28 solamente por lo que nuestro analisis sera mucho mas facil.
Para ello tenemos dos metodos el primero llamado hclust y el segundo llamado Agnes ambos metodos trabajan de forma matricial por tanto tenemos que transformar las matrices y sus distancias.
#transformacion de matriz
nov_new <- nov_new %>% as.matrix()
#Matriz de distancia
nov_new <- nov_new / rowSums(nov_new)
nov_dist <- dist(nov_new, method = "euclidian")
con el metodo de hclust tenemos las siguiente grafica de asociación, donde las palabras mas alejadas son las menos asociadas que lo podemos ver a trabajes de cuadros
nov_hclust <- hclust(nov_dist, method = "ward.D")
plot(nov_hclust, main = "Dendrograma - hclust", sub = "", xlab = "")
rect.hclust(nov_hclust, k = 10, border="red")
la diferencia con el metodo de agnes en realidad no es muy grande, sin embargo, este metodo nos muestra con más claridad las palabras mas aisladas de la asociación.
nov_agnes <- agnes(nov_dist, method = "average")
plot(nov_agnes, which.plots = 2, main = "Dendrograma - Agnes", sub = "", xlab = "")
rect.hclust(nov_agnes, k = 10, border = "red")