9. Bigramas
No artigo de hoje vamos ter uma abordagem um pouco diferente para analisar textos. Esta abordagem consiste em considerar que palavras em conjunto podem trazer mais contexto do que palavras em separado. Esta metodologia é chamada de n-gramas e consiste em considerar a sequência das palavras em uma frase. Um exemplo:
n-gramas é uma metodologia de mineração de textos
Nesta afirmação, considerando bigramas, temos a seguinte combinação:
- n-gramas / é
- é / uma
- uma / metodologia
- metodologia / de
- de / mineração
- minderação / de
- de / textos
Ainda expandindo este conceito, considerando trigramas, temos a seguinte combinação:
- n-gramas / é / uma
- é / uma / metodologia
- uma / metodologia / de
- de / metodologia / de
- metodologia / de / mineração
- de / mineração / de
- mineração / de / dados
Aplicando esta metodologia e algum pré-processamento adicional, podemos utilizar o que já aprendemos nos artigos anteriores e tirar melhores significados dos textos. Vamos aos códigos!
Dados do Twitter
Na aplicação de hoje, vamos escolher um assunto dos trending topics e capturar 200 tweets sobre esse determinado assunto. Clique aqui se você não sabe como usar o R para extrair dados da API to Twitter.
1. Autenticando na API
library(twitteR)
consumer_key <- "sua consumer_key"
consumer_secret <- "seu consumer_secret"
access_token <- "seu access_token"
access_secret <- "seu access_secret"
setup_twitter_oauth(consumer_key, consumer_secret, access_token, access_secret)
## [1] "Using direct authentication"
2. Listando os Trending Topics no Brasil.
trends <- getTrends(23424768) # este número se refere ao Brasil.
head(trends$name, 10) # retorna as 10 primeiras hashtags.
## [1] "#EliminaçãoPowerCouple" "Borja"
## [3] "#QuartaDetremuraSDV" "Britto"
## [5] "#CorreVerdevaldo" "Godoy Cruz"
## [7] "Com 15" "#SouDoTempoQue"
## [9] "DIA DE INTER" "HOJE TEM FLAMENGO"
3. Buscando a hashtag #EliminaçãoPowerCouple
library(dplyr)
tweets <- searchTwitter('#EliminaçãoPowerCouple', n = 200, resultType="recent", lang="pt-br") %>%
twListToDF() %>% # Converte o formato lista para data frame
as_tibble() %>% # Converte no formato tidy
select(id, text) # Seleciona apenas a coluna que contém o conteúdo de texto e o id
head(tweets, 5)
## # A tibble: 5 x 2
## id text
## <chr> <chr>
## 1 115389868172630… RT @JonasMattos_: Quem fez parte desses 57% da RT aqui …
## 2 115389867418501… RT @powercouple: Agora é com a Nicole e o Bimbi. Quem é…
## 3 115389856492753… "RT @eduucomenta: Eu não apareci aqui ! O site tava uma…
## 4 115389856184477… RT @JonasMattos_: Quem fez parte desses 57% da RT aqui …
## 5 115389851754871… "RT @GuiHenri190: #EliminaçãoPowerCouple Nicole e Bimb…
4. Pré-processamento, conforme já abordado no artigo anterior sobre dados do Twitter.
library(tidytext)
library(tm)
library(ptstem)
library(ggplot2)
# Pré-processamento
tweets$text <- tweets$text %>%
gsub(pattern = "RT ",replacement = "") %>% # Remove RT simples
gsub(pattern = "http\\S+\\s*",replacement = "") %>% # Remove URLs
gsub(pattern = "@\\w+: ",replacement = "") %>% # Remove @mentions
gsub(pattern = "#\\w+ ",replacement = "") %>% # Remove #hashtags
ptstem() # Retorno ao radical
# Formato tidy
tidytweets <- tibble(id = tweets$id, tweet = tweets$text)
head(tidytweets, 5)
## # A tibble: 5 x 2
## id tweet
## <chr> <chr>
## 1 115389868172630… "Quem fez parte desses 57% da aqui amores "
## 2 115389867418501… "Agora é com a Nicole e o Bimbi. Quem é #TimeNicelo? "
## 3 115389856492753… "Eu não apareci aqui ! O site tava uma merda, mas votei…
## 4 115389856184477… "Quem fez parte desses 57% da aqui amores "
## 5 115389851754871… " Nicole e Bimbi retornam e Brasil vai a loucura/ O Bra…
5. Tokenização e bigramas
Nesta etapa temos algo diferente e para ilustrar, farei a análise de dados tradicional, com unigramas (palavras únicas) e com bigramas:
tweets_unigramas <- tweets %>%
unnest_tokens(unigrama, text) %>%
filter(!unigrama %in% stopwords(kind = "pt")) %>%
filter(!unigrama == "eliminaçãopowercouple") %>% # Para remover a #hashtag de busca
count(unigrama, sort = TRUE)
tweets_unigramas
## # A tibble: 471 x 2
## unigrama n
## <chr> <int>
## 1 nicole 57
## 2 é 44
## 3 final 41
## 4 bimbi 40
## 5 votei 31
## 6 nicelo 28
## 7 casal 22
## 8 vamos 20
## 9 vai 19
## 10 tudo 18
## # … with 461 more rows
Até aqui, não há muita novidade além de pré-processamento de dados e análise de frequência. A seguir, como calcular as bigramas:
tweets %>%
unnest_tokens(bigrama, text, token = "ngrams", n = 2) %>%
count(bigrama, sort = TRUE)
## # A tibble: 1,186 x 2
## bigrama n
## <chr> <int>
## 1 nicole e 41
## 2 e bimbi 27
## 3 na final 26
## 4 nicelo na 16
## 5 com tudo 13
## 6 ju e 11
## 7 57 nicelo 10
## 8 aaaaaaa 57 10
## 9 fez parte 10
## 10 final famíliaaa 10
## # … with 1,176 more rows
Note que o papel das stopwords aqui continua grande e por conta disso, precisamos de algumas etapas adicionais para filtrar as stopwords que apareçam no primeiro ou no segundo termo do bigrama. Note que usamos a função separate()
do pacote tidyr que quebra a bigrama no espaço em branco entre as duas palavras, transformando a bigrama em duas colunas. Desta forma, podemos filtrar mais facilmente:
library(tidyr)
tweets_bigramas <- tweets %>%
unnest_tokens(bigrama, text, token = "ngrams", n = 2) %>%
separate(bigrama, c("palavra1","palavra2"), sep = " ") %>%
filter(!palavra1 %in% stopwords(kind = "pt")) %>%
filter(!palavra2 %in% stopwords(kind = "pt")) %>%
filter(!palavra1 == "eliminaçãopowercouple") %>%
filter(!palavra2 == "eliminaçãopowercouple") %>%
count(palavra1, palavra2, sort = TRUE)
tweets_bigramas
## # A tibble: 398 x 3
## palavra1 palavra2 n
## <chr> <chr> <int>
## 1 57 nicelo 10
## 2 aaaaaaa 57 10
## 3 fez parte 10
## 4 final famíliaaa 10
## 5 agora é 7
## 6 casal elimina 6
## 7 casal final 6
## 8 contra todas 6
## 9 é timenicelo 6
## 10 final elimi 6
## # … with 388 more rows
Este procedimento pode ser repetido para trigramas também de forma análoga. E você pode prosseguir com a elaboração de gráficos usando ggplot()
, conforme já demonstrado exaustivamente nos artigos anteriores.
Rede de Bigramas
A metodologia anterior é interessante para visualizar as bigramas mais frequentes, mas seria interessante poder ter uma visão mais ampla destas relações entre palavras. A seguir, mostro como podemos ter essa visão geral usando uma rede de palavras com os pacotes igraph
e ggraph
.
library(igraph)
library(ggraph)
tweets_bigramas %>%
filter(n > 2) %>% # Filtrando bigramas que aparecem mais do que 2 vezes, pelo menos.
graph_from_data_frame() %>% # Gera as relações direcionais entre palavras.
ggraph(layout = "fr") +
geom_edge_link(alpha = 0.5) + # Alpha para adicionar transparência as retas.
geom_node_point(color = "lightblue",
size = 3, alpha = 0.5) + # Definindo cor e tamanho dos pontos.
geom_node_text(aes(label = name),
vjust = 1, hjust = 1) + # vjust, hjust para deslocar os textos.
theme_void() # Remover eixos e cor do fundo.
Esta rede mostra algumas relações bem interessantes até sobre a estrutura de como os textos são escritos e enviados no Twitter. Mensagens de apoio, como por exemplo, “pessoal foquem somente”, ou reclamação como “terceiros típica participacão mediocre”. Note que estamos praticamente construindo a frase a partir de bigramas.
No entanto, ainda tem algo faltando neste gráfico: a direção das palavras (Palavra 1 –> Palavra 2). Para isso, precisamos de um código um pouquinho mais complexo:
set.seed(1234)
a <- grid::arrow(type = "closed", length = unit(.10, "inches"))
tweets_bigramas %>%
filter(n > 2) %>% # Filtrando bigramas que aparecem mais do que 2 vezes, pelo menos.
graph_from_data_frame() %>% # Gera as relações direcionais entre palavras.
ggraph(layout = "fr") +
geom_edge_link(aes(edge_alpha = n), show.legend = FALSE,
arrow = a, end_cap = circle(0.07,"inches")) +
geom_node_point(color = "lightblue",
size = 3, alpha = 0.5) + # Definindo cor e tamanho dos pontos.
geom_node_text(aes(label = name),
vjust = 1, hjust = 1) + # vjust, hjust para deslocar os textos.
theme_void() # Remover eixos e cor do fundo.
Neste gráfico acima temos 2 elementos novos:
- As setas indicam a direção das bigramas: Palavra 1 –> Palavra 2.
- As setas com cores mais escuras indicam bigramas mais frequentes. Note que: casal_eliminado, casal_final e fez_parte são as bigramas mais frequentes na tabela de frequência e aqui também possuem as setas mais escuras.
Considerações Finais
Neste artigos vimos o importante papel das bigramas em adicionar significado a um conjunto de textos, indo além da simples análise de frequência de palavras. Essa metodologia é útil até mesmo em conjunto de textos curtos, como do Twitter. Também vimos que é possível visualizar essas relações em formato de rede, demonstrando expressões mais usuais dentro deste domínio.