Carregando os Pacotes Necessários:

library(twitteR)
library(stringr)
library(lubridate)
library(tidytext)
library(dplyr)
library(ggplot2)
library(stringr)
library(tm)
library(rmarkdown)

Setando a Key da API:

Deixarei a Key apagada por motivos de segurança.

setup_twitter_oauth(consumer_key = "secreta",
                    consumer_secret = "secreta", 
                    access_token = "secreta", 
                    access_secret = "secreta")
## [1] "Using direct authentication"

Coletando os Tweets:

Nesse momento estamos coletando os tweets relacionados ao Boulos, desejamos 10000 tweets. Além disso, definimos a linguagem para português.

tweets.boulos <- searchTwitter("Boulos", n = 10000, lang = "pt-br")

Extraindo Informações:

Dos tweets coletados, extraimos o conteúdo do tweets, o usuário de quem escreveu, a data e o id. Ao final juntamos tudo isso em um objeto do tipo dataframe.

text <- as.character(rep(NA, length(tweets.boulos)))
screenname <- as.character(rep(NA, length(tweets.boulos)))
created = as.POSIXct(rep(NA, length(tweets.boulos)))
id = c()

for (i in 1:length(tweets.boulos)) {
  text[i] = tweets.boulos[[i]]$text
  screenname[i] = tweets.boulos[[i]]$screenName
  created[i] = tweets.boulos[[i]]$created
  id[i] = tweets.boulos[[i]]$id
}

x = data.frame(id = id, 
               screenname = screenname, 
               created = created,
               text = text, 
               stringsAsFactors = FALSE)

head(x, 3)

Em seguida limpamos os tweets

x$text <- str_replace_all(x$text,"\n", " ")

Dicionário de Palavras:

Para realizar a análise iremos usar o oplexicon, que basicamente nos diz a conotação das palavras em português. Tenha em mente: dependendo do contexto da análise as conotações das palavras podem mudar, por exemplo, se você estiver fazendo uma análise de tweets sobre futebol, talvez as palavras não tenham a mesma conotação de tweets sobre política. Porém, temos poucos dicionários desse tipo em português e o oplexicon é uma mão na roda, com ele conseguimos fazer uma série de análises.

Em seguida trazemos para um objeto as stopwords do pacote tm. Stopwords são palavras que não há conotação nem positiva, nem negativa, como: o, a, os, as, que, porém. Retira-las do nosso texto facilita e agiliza nossa análise, por isso a etapa de limpeza dos dados é tão importante.

stopwords <- tm::stopwords("pt-br")

Análise de Sentimentos:

Agora iremos começar a análise de sentimento de fato. Primeiro pegamos palavra por palavra de cada tweet, além de transformar tudo em minúscula. Em seguida retiramos as stopwords e todos os rt, pois eles não nos idicam nada. Por fim, juntamos as palavras com sua conotação e contamos sua ocorrência. Abaixo mostro as 50 mais usadas:

x %>% 
  unnest_tokens(token = "words", word, text) %>% 
  select(id, word) %>% 
  filter(!word %in% stopwords, !word == "rt") %>% 
  inner_join(bing, by = c("word" = "word")) %>% 
  count(word, sentiment, sort = TRUE) %>% 
  dplyr_row_slice(1:50)

Contamos a quantidade de palavras negativas e positivas. Vemos que há muito mais palavras positivas do que negativas, isso talvez reflita como o candidato é visto pela maioria das pessoas nas redes sociais. Isso não indica se é um bom ou mal candidato, só reflete, em partes, qual o sentimento das pessoas sobre ele no Twitter. De fato, na campanha de 2020 o candidato colocou todas as suas forças nas redes sociais e pesquisas mostram que seu eleitorado é na maioria composto por jovens universitários, isso reflete diretamente no seu posicionamento no Twitter.

x %>% 
  unnest_tokens(token = "words", word, text) %>% 
  select(id, word) %>% 
  filter(!word %in% stopwords, !word == "rt") %>% 
  inner_join(bing, by = c("word" = "word")) %>% 
  count(word, sentiment, sort = TRUE) %>%
  group_by(sentiment) %>% 
  summarise(n = sum(n))

O gráfico abaixo só reflete o que eu havia dito anteriormente, porém de maneira visual.

x %>% 
  unnest_tokens(token = "words", word, text) %>% 
  filter(!word %in% stopwords, !word == "rt") %>% 
  select(id, created, word) %>% 
  inner_join(bing, by = c("word" = "word")) %>% 
  select(id, created, sentiment) %>% 
  count(id, created, sentiment) %>% 
  filter(sentiment == "positive" | sentiment == "negative") %>%
  group_by(Date = as.Date(ymd_hms(created)), sentiment) %>% 
  summarize(total = sum(n)) %>% 
  ggplot(aes(x = sentiment, y = total, fill = sentiment)) + 
  geom_bar(stat = "identity", show.legend = FALSE) +
  labs(x = "Sentimento", 
       y = "Tweets", 
       title = "Análise de Sentimento - Boulos 28/11/2020") +
  scale_x_discrete(position = "bottom", 
                   labels =  c("negative" = "Negativo", 
                               "positive" = "Positivo"))

### Para finalizar pegamos, dos dados que coletamos, os usuários com mais matchs entre palavras. Geralmente, nesse tipo de análise, a definição se um tweet possui conotação positiva ou negativa é feita pela subtração do número de palavras positivas pelo número de palavras negativas. Se o resultado da subtração for positivo, muito provavelmente, o sentimento do tweet é positivo, o inverso também é válido.

No exemplo abaixo podemos ver realmente isso, pegando como exemplo o usuário com maior diferença entre positivos do que negativos vemos que de fato ele tem a visão pró Boulos e isso é refletido pelo grande excesso de palavras positivas.

x %>% 
  unnest_tokens(token = "words", word, text) %>% 
  filter(!word %in% stopwords, !word == "rt") %>% 
  select(id, screenname, created, word) %>% 
  inner_join(bing, by = c("word" = "word")) %>% 
  count(screenname, sentiment, sort = TRUE) %>% 
  filter(sentiment != "neutral") %>% 
  group_by(sentiment) %>% 
  top_n(10) %>% 
  ggplot(aes(x=factor(screenname), y = n, fill= sentiment))+ 
  geom_bar(stat='identity') +
  theme(axis.text.x = element_text(angle=90)) +
  labs(x = '', y = '', 
       title = "Análise de Sentimento Boulos - 28/11/2020", 
       subtitle = "por usuário", 
       fill = "Sentimento") +
  scale_fill_discrete(labels = c("negative" = "Negativo", 
                                 "positive" = "Positive"))