Análisis de chats en WhatsApp: Parte 2 — Análisis de sentimientos y visualización de Datos con R

Image for post
Image for post
Dashboard de visualización de datos chat WhatsApp, link al final del artículo

¿Quién tiene un léxico más diverso?

# DIVERSIDAD DE LÉXICO
miChat %>%
unnest_tokens(input = text,
output = word) %>%
filter(!word %in% remover_palabras) %>%
group_by(author) %>%
summarise(lex_diversity = n_distinct(word)) %>%
arrange(desc(lex_diversity)) %>%
ggplot(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, 500))) +
geom_text(aes(label = scales::comma(lex_diversity)), hjust = -0.1) +
ylab("Diversidad léxica") +
xlab("Usuario") +
ggtitle("Diversidad de léxico en la conversación") +
coord_flip()
Image for post
Image for post
Análisis WhatsApp con R — Diversidad de léxico

Palabras únicas por usuario

# PALABRAS ÚNICAS POR ELLA
palabras_unicas_ella <- miChat %>%
unnest_tokens(input = text,
output = word) %>%
filter(author != "Ella") %>%
count(word, sort = TRUE)
miChat %>%
unnest_tokens(input = text,
output = word) %>%
filter(author == "Ella") %>%
count(word, sort = TRUE) %>%
filter(!word %in% palabras_unicas_ella$word) %>%
# SELECCIONAR SÓLO PALABRAS QUE NADIE MÁS USA
top_n(n = 15, n) %>%
ggplot(aes(x = reorder(word, n), y = n)) +
geom_col(show.legend = FALSE) +
ylab("Número de veces que se usó la palabra") + xlab("Palabras") +
coord_flip() +
ggtitle("Top de palabras únicas usadas por Ella")
# PALABRAS ÚNICAS POR ÉL
palabras_unicas_el <- miChat %>%
unnest_tokens(input = text,
output = word) %>%
filter(author != "Él") %>%
count(word, sort = TRUE)
miChat %>%
unnest_tokens(input = text,
output = word) %>%
filter(author == "Él") %>%
count(word, sort = TRUE) %>%
filter(!word %in% palabras_unicas_el$word) %>%
# SELECCIONAR SÓLO PALABRAS QUE NADIE MÁS USA
top_n(n = 15, n) %>%
ggplot(aes(x = reorder(word, n), y = n)) +
geom_col(show.legend = FALSE) +
ylab("Número de veces que se usó la palabra") + xlab("Palabras") +
coord_flip() +
ggtitle("Top de palabras únicas usadas por Él")
Image for post
Image for post
Análisis WhatsApp con R — Palabras únicas de Ella
Image for post
Image for post
Análisis WhatsApp con R — Palabras únicas de Él

Análisis de sentimientos con Emoji Sentiment Ranking

# USAMOS EL PAQUETE RVEST
library(rvest)
# FETCH DE PÁGINA HTML EMOJI SENTIMENT RANKING 1.0
url_base <- "http://kt.ijs.si/data/Emoji_sentiment_ranking/index.html"
doc <- read_html(url_base)
# BUSCAR TABLA DE EMOJI Y PROCESO
tabla_emojis <- doc %>%
html_node("#myTable") %>%
html_table() %>%
as_tibble()
# OBTENER PUNTAJE DE SENTIMIENTO Y LIMPIAR
sentimiento_emoji <- tabla_emojis %>%
select(1,6:9) %>%
set_names("char", "negativo","neutral","positivo","sent.score")
# EXTRAER EMOJI Y UNIR CON SENTIMIENTO
emoji_chat <- miChat %>%
unnest(emoji, emoji_name) %>%
mutate( emoji = str_sub(emoji, end = 1)) %>%
inner_join(sentimiento_emoji, by=c("emoji"="char"))
# VISUALIZACIÓN PREVIA
emoji_chat %>%
select(-source, -day, -estacion) %>%
slice(1207:1219) %>%
kable() %>%
kable_styling(font_size = 10)
Image for post
Image for post
Análisis WhatsApp con R — Preview Emoji Sentiment Ranking
# OCURRENCIAS DE SENTIMIENTOS POR EMOJIS, POR USUARIO
emoji_sentimiento_usuarios <- emoji_chat %>%
group_by(author) %>%
summarise(
positivo=mean(positivo),
negativo=mean(negativo),
neutral=mean(neutral),
balance=mean(sent.score)
) %>%
arrange(desc(balance))
# FORMATO DE DATOS PARA REALIZAR PLOT
emoji_sentimiento_usuarios %>%
mutate( negativo = -negativo,
neutral.positivo = neutral/2,
neutral.negativo = -neutral/2) %>%
select(-neutral) %>%
gather("sentiment","mean", -author, -balance) %>%
mutate(sentiment = factor(sentiment, levels = c("negativo", "neutral.negativo", "positivo", "neutral.positivo"), ordered = T)) %>%
ggplot(aes(x=reorder(author,balance), y=mean, fill=sentiment)) +
geom_bar(position="stack", stat="identity", show.legend = F, width = .5) +
scale_fill_manual(values = brewer.pal(4,"RdYlGn")[c(1,2,4,2)]) +
ylab(" - Negativo / Neutral / Positivo +") + xlab("Usuario") +
ggtitle("Análisis de sentimientos por usuario","Basado en el puntaje promedio de sentimientos por emojis") +
coord_flip() +
theme_minimal()
Image for post
Image for post
Análisis WhatsApp con R — Análisis de sentimientos con Emoji Sentiment Ranking

Análisis de sentimientos con AFINN

library(textdata)# OBTENER LÉXICO POSITIVO/NEGATIVO DEL PACKAGE DE LEXICON 
lexico_negpos <- get_sentiments("afinn") # INTENSIDAD DE VALOR
# PREVIEW DEL FORMATO DE LEXICO
lexico_negpos %>%
head(10) %>%
kable() %>%
kable_styling(full_width = F, font_size = 11)
# PREVIEW CUÁLES SON LOS VALORES POSIBLES
table(lexico_negpos$value) %>%
head(10) %>%
kable() %>%
kable_styling(full_width = F, font_size = 11)
Image for post
Image for post
Análisis WhatsApp con R — Preview Léxico AFINN
# EXTRAER EMOJIS
emoji_sentimiento_score <- miChat %>%
select( emoji, emoji_name) %>%
unnest( emoji, emoji_name) %>%
mutate( emoji = str_sub(emoji, end = 1)) %>%
mutate( emoji_name = str_remove(emoji_name, ":.*")) %>%
distinct() %>%
unnest_tokens(input=emoji_name, output=emoji_words) %>%
inner_join(lexico_negpos, by=c("emoji_words"="word"))
# CREAR TABLA DE 3 COLUMNAS
bind_cols(
slice(emoji_sentimiento_score, 01:10),
slice(emoji_sentimiento_score, 11:20),
slice(emoji_sentimiento_score, 21:30)
) %>%
kable() %>%
kable_styling(full_width = F, font_size = 11)
Image for post
Image for post
Análisis WhatsApp con R — Preview Léxico AFINN y Emojis
# EXTRAER EMOJIS
emoji_chat <- miChat %>%
unnest(emoji, emoji_name) %>%
mutate( emoji = str_sub(emoji, end = 1)) %>%
mutate( emoji_name = str_remove(emoji_name, ":.*"))
# TOKENIZAR EL NOMBRE DE EMOJI
emoji_chat <- emoji_chat %>%
select(author, emoji_name) %>%
unnest_tokens(input=emoji_name, output=emoji_words)
# JOIN CON LEXICON
usuario_summary <- emoji_chat %>%
inner_join(lexico_negpos, by=c("emoji_words"="word")) %>%
count(author, value) %>%
group_by(author) %>%
mutate(mean=n/sum(n)) %>%
ungroup()
# COLORES Y GRÁFICA
reordenar_niveles <- c(-3,-2,-1,3,2,1)
colores <- c("#d7191c","#fdae61","#ffffbf","#1a9641","#a6d96a","#ffffbf")
mis_colores <- brewer.pal(5,"RdYlGn")[c(1,2,3,5,4,3)]
# PLOT DE LA GRÁFICA
usuario_summary %>%
mutate( mean = ifelse(value<0, -mean, mean)) %>%
group_by(author) %>%
mutate( balance = sum(mean)) %>%
ungroup() %>%
mutate( value = factor(value, levels = reordenar_niveles, ordered=T)) %>%
ggplot(aes(x=reorder(author,balance), y=mean, fill=value)) +
geom_bar(stat="identity",position="stack", show.legend = F, width = .5) +
scale_fill_manual(values = mis_colores) +
xlab("Usuario") + ylab("Escala de netagivo a positivo") +
coord_flip() +
ggtitle("Análisis de sentimientos por uso de emojis", "Uso de package Lexicon") +
theme_minimal()
Image for post
Image for post
Análisis WhatsApp con R — Análisis de sentimientos con Léxico AFINN

¿Cuál es la emoción más frecuente? (Con EmoLex)

# OBTENER OTRO LÉXICO CON NOMBRE DE SENTIMIENTOS
lexico_sentimientos <- get_sentiments("nrc")
# EXTRAER EMOJIS
emoji_emocion <- miChat %>%
select( emoji, emoji_name) %>%
unnest( emoji, emoji_name) %>%
mutate( emoji = str_sub(emoji, end = 1)) %>%
mutate( emoji_name = str_remove(emoji_name, ":.*")) %>%
unnest_tokens(input=emoji_name, output=emoji_words) %>%
inner_join(lexico_sentimientos, by=c("emoji_words"="word")) %>%
# REMOVER CLASIFICACIÓN NEGATIVA/POSITIVA
filter(!sentiment %in% c("negative","positive")) %>%

# MANTENER SÓLO LOS 4 EMOJI MÁS FRECUENTES PARA CADA SENTIMIENTO
count(emoji, emoji_words, sentiment) %>%
group_by(sentiment) %>%
top_n(4,n) %>%
slice(1:4) %>%
ungroup() %>%
select(-n)
# PONER TABLAS JUNTAS
bind_cols(
slice(emoji_emocion, 01:16),
slice(emoji_emocion, 17:32)
) %>%
kable() %>%
kable_styling(full_width = F, font_size = 11)
Image for post
Image for post
Análisis WhatsApp con R — Preview NRC Emotion Lexicon
# JOIN CON EMOJIS
sentimiento_chat <- emoji_chat %>%
inner_join(lexico_sentimientos, by=c("emoji_words"="word")) %>%
# REMOVER CLASIFICACIÓN POITIVA/NEGATIVA
filter(!sentiment %in% c("negative","positive"))
# PLOT DE EMOCIONES MAYORMENTE EXPRESADAS
sentimiento_chat %>%
count(sentiment) %>%
ggplot(aes(x=reorder(sentiment,n), y=n)) +
geom_col(aes(fill=n), show.legend = FALSE, width = .1) +
geom_point(aes(color=n), show.legend = FALSE, size = 3) +
coord_flip() +
ylab("Número de veces expresado") + xlab("Emoción") +
scale_fill_gradient(low="#2b83ba",high="#d7191c") +
scale_color_gradient(low="#2b83ba",high="#d7191c") +
ggtitle("Emoción expresada con mayor frecuencia","Expresado por uso de emojis") +
theme_minimal()
Image for post
Image for post
Análisis WhatsApp con R — Emoción más expresada con NRC Emotion Lexicon

¿Qué emociones expresan con mayor frecuencia cada usuario?

# PLOT DE EMOCIONES POR USUARIO
sentimiento_chat %>%
count(author, sentiment) %>%
left_join(filter(lexico_sentimientos, sentiment %in% c("negative","positive")),by=c("sentiment"="word")) %>%
rename( sentimiento = sentiment.y) %>%
mutate( sentimiento = ifelse(is.na(sentimiento), "neutral", sentimiento)) %>%
mutate( sentimiento = factor(sentimiento, levels = c("negative", "neutral", "positive"), ordered=T) ) %>%
group_by(author) %>%
top_n(n = 8, n) %>%
slice(1:8) %>%
ggplot(aes(x = reorder(sentiment, n), y = n, fill = sentimiento)) +
geom_col() +
scale_fill_manual(values = c("#d7191c","#fdae61", "#1a9641")) +
ylab("Número de veces expresado") +
xlab("Emoción") +
coord_flip() +
facet_wrap(~author, ncol = 3, scales = "free_x") +
ggtitle("Emociones mayormente expresadas por usuario", "Expresado por uso de emojis") +
theme_minimal() + theme(legend.position = "bottom")
Image for post
Image for post
Análisis WhatsApp con R — Análisis de emociones por usuario con NRC Emotion Lexicon

Otros artículos que he escrito

Aprendiz constante, amante de la tecnología. #G3ekArmy, Web Developer & Data Enthusiast. Coordinador académico & Instructor en KMMX. Organizador de #KotlinCDMX.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store