Clase 31 - Introducción a la Minería de Texto
1 Lectura de datos
Para la realización de esta actividad usaremos las siguientes bibliotecas:
library("rwhatsapp")
library("dplyr")
library("ggplot2")
library("lubridate")
library("tidyr")
library("ggimage")
library("tidytext")
library("stopwords")
library("plotly")La lectura de los datos se hará con el siguiente comando. Mensajes sin usuarios serán removidos:
## Cargar los datos
chat = rwa_read("WAppDiinf.txt") # Lectura
chat = filter(chat, !is.na(author)) # Remover mensajes sin autor
print(levels(chat$author))## [1] "+1 (403) 990-5727" "+56 9 5895 4518" "+56 9 6845 6981"
## [4] "+56 9 7686 7402" "+56 9 8234 9110" "+56 9 8286 1145"
## [7] "+56 9 8736 1782" "+56 9 9231 6070" "+56 9 9333 9553"
## [10] "+56 9 9365 6879" "+56 9 9879 4998" "+56 9 9918 1562"
## [13] "Cristobal Acosta" "Diego Caro" "Felipe Bello"
## [16] "José Luis Jara" "Leo Medina" "Manuel Villalobos"
## [19] "Mario Inostroza" "Maurício Marin" "Max Chacón"
## [22] "Pablo Roman" "Roberto González"
chat=filter(chat, (author=="Roberto González") | (author=="Mario Inostroza") | (author=="Leo Medina") |
(author=="Maurício Marin") | (author=="Max Chacón") | (author=="Diego Caro") | (author=="José Luis Jara") |
(author=="Felipe Bello") | (author=="Cristobal Acosta") | (author=="Pablo Roman") |
(author=="Manuel Villalobos"))
## Ver los datos
knitr::kable(head(chat,n = 5))| time | author | text | source | id | emoji | emoji_name |
|---|---|---|---|---|---|---|
| 2019-10-20 16:53:37 | Cristobal Acosta | Todo bien por acá | WAppDiinf.txt | 6 | NULL | NULL |
| 2019-10-20 17:46:37 | Leo Medina | Grande Gonzalo! | WAppDiinf.txt | 35 | NULL | NULL |
| 2019-10-20 18:31:37 | Roberto González | Array suspendido | WAppDiinf.txt | 38 | NULL | NULL |
| 2019-10-20 18:31:37 | Roberto González | Proximamente se viene comunicado :( | WAppDiinf.txt | 39 | NULL | NULL |
| 2019-10-20 18:32:37 | Pablo Roman | Por mi lado estamos bien. | WAppDiinf.txt | 40 | NULL | NULL |
2 Registro de actividades
El siguiente gráfico muestra la actividad del grupo en el tiempo:
theme_set(theme_minimal())
chat = mutate(chat,day = date(time))
chat = mutate(chat,date = format(as.Date(chat$time),"%Y/%m"))
freq = count(chat,date)
grafico = ggplot(freq,aes(x = date, y = n)) +
geom_bar(stat = "identity") +
ylab("") + xlab("") + theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
ggtitle("Registro de Actividades")
ggplotly(grafico)3 Actividad por usuario
La actividad por usuario es la siguiente:
chat = mutate(chat,day = date(time))
frec = count(chat,author)
grafico = ggplot(frec,aes(x = reorder(author, n), y = n)) +
geom_bar(stat = "identity") +
ylab("") + xlab("") +
coord_flip() +
ggtitle("Cantidad de Mensajes")
ggplotly(grafico)4 Uso de emojis
¿Usarán emojis los académicos de este grupo del Diinf? Estos son los 5 emojis más usados por los académicos:
frec=unnest(chat,emoji)
frec=count(frec,author, emoji, sort = TRUE)
frec=dplyr::group_by(frec,author)
frec=top_n(frec,n = 5, n)
grafico=ggplot(frec,aes(x = reorder(emoji, n), y = n, fill = author)) +
geom_col(show.legend = FALSE) +
ylab("") +
xlab("") +
coord_flip() +
facet_wrap(~author, ncol = 4, scales = "free_y") +
ggtitle("Emojis más utilizados")
ggplotly(grafico)5 Palabras más utilizadas
Sin aplicar ningún filtro en el texto, las palabras más utilizadas por los académicos son:
frec=unnest_tokens(chat,input = text,
output = word)
frec=count(frec,author, word, sort = TRUE)
frec=group_by(frec,author)
frec= top_n(frec,n = 5, n)
grafico=ggplot(frec,aes(x = reorder_within(word, n, author), y = n, fill = author)) +
geom_col(show.legend = FALSE) +
ylab("") +
xlab("") +
coord_flip() +
facet_wrap(~author, ncol = 4, scales = "free_y") +
scale_x_reordered() +
ggtitle("Palabras más utilizadas")
ggplotly(grafico)Como ven, hay palabras que se repiten que no tienen relevancia. Estas serán eliminadas:
## Palabras para remover
no_relevantes = c(tm::stopwords("es"),"omitido","https","multimedia","twitter.com","status","youtube","video",
"tambien","www.ncbi.nlm.nih.gov")Ahora repetiremos la actividad:
frec=unnest_tokens(chat,input = text,
output = word)
frec=filter(frec,!word %in% no_relevantes) #Aplicación de filtro
frec=frec[which(nchar(frec$word)>3),] #Palabras con más de 3 letras
frec=count(frec,author, word, sort = TRUE)
frec=group_by(frec,author)
frec= top_n(frec,n = 5, n)
grafico=ggplot(frec,aes(x = reorder_within(word, n, author), y = n, fill = author)) +
geom_col(show.legend = FALSE) +
ylab("") +
xlab("") +
coord_flip() +
facet_wrap(~author, ncol = 4, scales = "free_y") +
scale_x_reordered() +
ggtitle("Palabras más utilizadas")
ggplotly(grafico)¿Cómo se reirá la gente del Diinf?
frec=unnest_tokens(chat,input = text,
output = word)
frec=filter(frec,!word %in% no_relevantes) #Aplicación de filtro
idx=which(grepl("jaja", frec$word, fixed = TRUE)=="TRUE")
idx=c(idx,which(grepl("haha", frec$word, fixed = TRUE)=="TRUE"))
idx=c(idx,which(grepl("ajj", frec$word, fixed = TRUE)=="TRUE"))
idx=c(idx,which(grepl("ahah", frec$word, fixed = TRUE)=="TRUE"))
frec=frec[idx,]
frec=count(frec,author, word, sort = TRUE)
frec=group_by(frec,author)
frec= top_n(frec,n = 5, n)
grafico=ggplot(frec,aes(x = reorder_within(word, n, author), y = n, fill = author)) +
geom_col(show.legend = FALSE) +
ylab("") +
xlab("") +
coord_flip() +
facet_wrap(~author, ncol = 4, scales = "free_y") +
scale_x_reordered() +
ggtitle("Palabras más utilizadas")
ggplotly(grafico)6 Diversidad léxica
La diversidad léxica de los académicos es la siguiente.
frec=unnest_tokens(chat,input = text,
output = word)
frec=filter(frec,!word %in% no_relevantes) #Aplicación de filtro
frec=group_by(frec,author)
frec=summarise(frec,lex_diversity = n_distinct(word))
frec=arrange(frec,desc(lex_diversity))
grafico=ggplot(frec,aes(x = reorder(author, lex_diversity),
y = lex_diversity,
fill = author)) +
geom_col(show.legend = FALSE) +
scale_y_continuous(expand = (mult = c(0, 0, 0, 10000))) +
geom_text(aes(label = scales::comma(lex_diversity)), hjust = -0.3) +
ylab("Palabras únicas") +
xlab("") +
ggtitle("Diversidad Léxica") +
coord_flip()
ggplotly(grafico)7 Wordcloud
Para generar la nube de palabras consideraremos las siguientes bibiotecas:
library("tm")
library("SnowballC")
library("wordcloud")
library("RColorBrewer")
library("stringr")
library("caret")
library("dplyr")El procesamiento del texto es el siguiente:
frec=unnest_tokens(chat,input = text,
output = word)
frec=filter(frec,!word %in% no_relevantes) #Aplicación de filtro
frec=frec[which(nchar(frec$word)>3),] #Palabras con más de 3 letras
corpus = Corpus(VectorSource(frec$word)) # formato de texto
## Transformación del Texto
# lleva a minúsculas
texto = tm_map(corpus, tolower)
# quita espacios en blanco
texto = tm_map(corpus, stripWhitespace)
# quita la puntuación
texto = tm_map(texto, removePunctuation)
# quita los números
texto = tm_map(texto, removeNumbers)
# remueve palabras vacías genericas
texto = tm_map(texto, removeWords, no_relevantes)
# crea matriz de términos
tdm = TermDocumentMatrix(texto)Creación de nube de palabras
# lo vuelve una matriz
matriz = as.matrix(tdm)
# lo ordena y suma
v = sort(rowSums(matriz),decreasing=TRUE)
# lo nombra y le da formato de data.frame
df = data.frame(word = names(v),freq=v)
### Trazar frecuencia de palabras
barplot(df[1:10,]$freq,
las = 2,
names.arg = df[1:10,]$word,
col ="lightblue",
main ="Palabras más frecuentes",
ylab = "Frecuencia de palabras")## Nube de Palabras
wordcloud(words = df$word,
freq = df$freq,
min.freq = 6,
max.words=100,
random.order=FALSE,
rot.per=0.35,
colors=brewer.pal(8, "Dark2"))8 Análisis de Sentimientos (básico)
Primero definiremos un tema para los gráficos.
library("purrr")
tema_graf =
theme_minimal() +
theme(text = element_text(family = "serif"),
panel.grid.minor = element_blank(),
strip.background = element_rect(fill = "#EBEBEB", colour = NA),
legend.position = "none",
legend.box.background = element_rect(fill = "#EBEBEB", colour = NA))Luego, ordenaremos los datos y emplearemos un diccionario de puntuación de sentimientos.
frec=unnest_tokens(chat,input = text,
output = word)
frec=filter(frec,!word %in% no_relevantes) #Aplicación de filtro
frec=frec[which(nchar(frec$word)>3),] #Palabras con más de 3 letras
afinn = read.csv("lexico_sentimientos.csv",sep=";",header=T,
encoding ="UTF-8",check.names = F)
afinn = data.frame(afinn)
colnames(afinn)=c("word","score","ingles")
frec=merge(frec,afinn,by = "word")
frec$emoji=NULL
frec$emoji_name=NULL
frec= mutate(frec,Tipo = ifelse(score > 0, "Positiva", "Negativa"))
frec=mutate(frec,score = ifelse(is.na(score), 0, score)) #Ocultamos palabras que no tienen puntaje
#Positivo
sentimiento = "Positiva"
frec2 = filter(frec,Tipo == sentimiento)
frec2=group_by(frec2,author)
frec2=count(frec2,word, sort = T)
frec2=top_n(frec2,n = 10, wt = n)
grafico=ggplot(frec2) +
aes(word, n, fill = author) +
geom_col() +
facet_wrap("author", ncol = 2, scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = sentimiento) + tema_graf
ggplotly(grafico)#Negativa
sentimiento = "Negativa"
frec2 = filter(frec,Tipo == sentimiento)
frec2=group_by(frec2,author)
frec2=count(frec2,word, sort = T)
frec2=top_n(frec2,n = 10, wt = n)
grafico=ggplot(frec2) +
aes(word, n, fill = author) +
geom_col() +
facet_wrap("author", ncol = 2, scales = "free") +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
labs(title = sentimiento) + tema_graf
ggplotly(grafico)Más detalles pueden ser encontrados en este link.