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.
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")
# 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
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)
# 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 |
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)
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"))