1. Escopo

Se você, assim como eu, trabalha com análise ou ciência de dados, deve estar familiarizado com o fato de que os dados são gerados o tempo todo em frequências cada vez mais rápidas. Academicamente, somos condicionados a lidar com dados estruturados, ou seja, dados tabulares ou retangulares que são em grande parte numéricos. Contudo, no mundo real, muitos dos dados que proliferam hoje são desestruturados, pesados e geralmente em formato de texto.

Desta forma, nesse post eu abordo um passo a passo simples de interpretação da linguagem natural utilizando dados em formato de texto. A ideia não foi fazer algo mais extenso partindo do webscraping, estruturação de dados, até o análise dos dados. Mas sim, buscar um banco de dados já estruturado, porém em formato de texto, e elaborar um guia de procedimentos básicos que permitam extrair insights desses dados.

Para isso, faço uso de um conjunto de dados reais que contém uma avaliação sobre o “sentimento” dos usuários do Twitter ao escrever um post. Distribuído em 40 mil observações, esse banco de dados contem além dos 13 rótulos dados aos sentimentos(como por exemplo: felicidade, tristeza e raiva), apresenta a identificação do autor do tweet, bem como a descrição na íntegra do próprio tweet.

2. Análise descritiva

2.1 Download do banco e dos Pacotes necessários

library(readr)    
library(ggplot2)  
library(ggthemes) 
library(dplyr)    
library(stringr) 
library(gridExtra)
library(gutenbergr)
library(tidytext)
library(knitr)
library(tidyr)
library(knitr)
library(igraph)
library(ggraph)
library(wordcloud)
data(stop_words)
dados  =  read_csv("text_emotion.csv")

2.1 Tratando o Banco de Dados

# Retirando vari攼㸱vel sem interpretabilidade 
dados = dados[,-1]
# Fatorizando os Autores
dados$author = as.factor(dados$author) 
# Fatorizando os Sentimentos
dados$sentiment = as.factor(dados$sentiment)
# Criar vari攼㸱vel de contagem de cita攼㸷昼㸵es 
dados$citacoes =  sapply(dados$content, function(x) str_count(x, '@'))
dados$citacoes = as.factor(dados$citacoes)
# Criar vari攼㸱vel de contagem de cita攼㸷昼㸵es 
dados$citacoes =  sapply(dados$content, function(x) str_count(x, '@'))
dados$citacoes = as.factor(dados$citacoes)
# Criar vari攼㸱vel de contagem de Caracteres 
dados$caracteres = nchar(dados$content, type = "chars",allowNA = FALSE,keepNA = NA)
dados$caracteres = as.factor(dados$caracteres)

summary(dados[,-3],maxsum = 10)
##      sentiment               author         citacoes       caracteres   
##  neutral  :8638   MissxMarisa   :   23   0      :20834   137    :  618  
##  worry    :8459   ChineseLearn  :   22   1      :18268   136    :  521  
##  happiness:5209   erkagarcia    :   19   2      :  737   47     :  471  
##  sadness  :5165   MiDesfileNegro:   19   3      :  100   45     :  428  
##  love     :3842   lost_dog      :   18   4      :   34   48     :  422  
##  surprise :2187   tsarnick      :   17   5      :   16   135    :  419  
##  fun      :1776   KimmiMcfly    :   15   6      :    6   41     :  416  
##  relief   :1526   linnetwoods   :   15   8      :    2   42     :  414  
##  hate     :1323   cece_newnew   :   14   7      :    1   39     :  413  
##  (Other)  :1875   (Other)       :39838   (Other):    2   (Other):35878

2.2 Análise Gráfica Univariada do Banco de Dados

palette = colorRampPalette(colors=c("#000000", "#FFFFFF"))
barplot(sort(table(dados$caracteres),decreasing = TRUE)[1:10], main = ' Nro. de Caracteres vs Tweet', xlab= 'Numero de Caracteres', ylab= 'Frequencia', col = palette(10),border="red", density=1000,font.axis = 3,font.lab=2, cex.lab=1,cex.axis = 0.5)

barplot(sort(table(dados$author),decreasing = TRUE)[1:10], main = '10 Principais Autores', xlab= '10 Principais Autores dos Tweets', ylab= '', col = palette(10), las=1,horiz = TRUE ,border="red", density=1000, space=c(rep(0.5,10)),font.axis = 3, font.lab=2, cex.lab=1,cex.axis = 1)

x = barplot(sort(prop.table(table(dados$sentiment))),horiz = FALSE,las=2, main = 'Distribuicao dos Sentimentos', col =sort(palette(13),decreasing =TRUE),border="red",
density=1000, ylab=  'Frequencia Relativa (%)',font.axis = 3,font.lab=2, cex.lab=1,cex.axis = 1,xaxt="n", ylim=c(-.1,0.25),yaxt ='n')
labs = paste(names(table(dados$sentiment)))
text(cex=1, x=x-.25, y=-0.05, labs, xpd=TRUE, srt=45)
axis(2,at=seq(0,0.25,0.05))

barplot(sort(prop.table(table(dados$citacoes)),decreasing = TRUE),horiz = FALSE,las=2, main = 'Nro. de Citacoes vs Tweet',beside = FALSE,border="red",
density=1000,las=1, xlab= 'Numero de Citacoes por Tweet', ylab = 'Frequencia Relativa (%)',font.axis = 3, font.lab=2, cex.lab=1,cex.axis = 1)

2.2 Análise Gráfica Multivariada do Banco de Dados

# Criando um banco de dados com a frequencia das palavras 
tidy_dados = dados %>%
  unnest_tokens(word, content) %>%
  anti_join(stop_words)
frequencia = tidy_dados %>%  count(word, sort = TRUE)
# 10 Palavras Frequentes nos Tweets
ref = frequencia[1:10,]
kable(ref)
word n
day 3145
quot 1855
http 1837
love 1635
happy 1484
lol 1436
time 1387
im 1263
amp 1159
night 1091

2.2.3 Clusterização Hierarquizada (Sentimento -> Palavras)

Perceba que a clusterização hierarquizada pela associação das palavras aos sentimentos sugeriu 4 grupos. Ao analisar o gráfico podemos destacar um grau de felicidade crescente entre esses grupos.

palavras=tidy_dados[,c(1,5)]
wordnetwork <- head(palavras, 46)
wordnetwork <- graph_from_data_frame(wordnetwork)
wordnetwork2 <- as.undirected(wordnetwork)
comm <- cluster_fast_greedy(wordnetwork2, weights = E(wordnetwork2)$n)
plot_dendrogram(comm)

2.2.3 Nuvem de Palavras

Uma nuvem de palavras é “uma imagem composta de palavras usadas em um determinado texto ou assunto, em que o tamanho de cada palavra indica sua frequência ou importância”. Ela funciona de maneira bem simples: quanto mais vezes uma palavra específica aparecer no seu texto, maior e mais arrojada aparecerá na sua nuvem de palavras.

A vantagem de usar a Nuvem de Palavras é que elas podem adicionar clareza durante a análise de um texto, comunicando um certo comportamento dos dados. Ou seja, revelar certos tipos de padrões de escrita com base na frequência de palavras.

### Nuvem de palavras 
wordcloud(words = frequencia$word, freq = frequencia$n, min.freq = 1,
          max.words=200, random.order=FALSE, rot.per=0.35, 
          colors=brewer.pal(8, "Dark2"))