Acesso e Análise de Dados do Twitter
Introdução
Na aula de hoje, vamos aprender como acessar e fazer algumas análises com base nas APIs de dados do Twitter. Nosso foco será em:
Aprender diferentes possibilidades de acesso aos dados das duas APIs do Twitter
Exemplos de análises básicas dos dados do Twitter.
Breve introdução à análise de redes, via pacote igraph.
Replicação de alguns exemplos do artigo de Calvo e Aruguete, Time to Retweet.
Acesso a dados do Twitter.
Para acessar a API do Twitter, utilizaremos o pacote rtweet. Nosso primeiro passo é instalar o pacote.
# Ativar rtweet
#install.packages("rtweet") # somente uma vez
library(rtweet)
# ativar outros pacotes
library(tidyverse)
library(igraph)
library(broom)
Solicitando sua credenciais.
Conforme aprendemos na aula passada, algumas APIs exigem um cadastro prévio para dar a devida autorização para seus acessos a dados. Este é o caso do Twitter. Para solicitar as credenciais, vocÊ precisa: 1) ter uma conta no twitter, 2) criar uma conta de desenvolvedor do twitter. O pacote rtweet
possui um excelente tutorial sobre como solicitar acesso de desenvolvedor.
vignette("auth", package = "rtweet")
Após receber suas credenciais, você deve fazer seu login. Primeiro vamos criar objetos com nossas chaves.
Agora, vamos liberar nosso acesso.
create_token(app=app_name,
consumer_key=consumer_key, consumer_secret=consumer_secret,
access_token = access_token, access_secret = access_token_secret)
Pronto. A função create_token salva no seu ambiente do R sua senha de acesso. A priori, se estiver funcionando corretamente, você não precisa repetir essa autorização outras vezes. Para testar, você pode abrir e fechar sua sessão no R para verificar o funcionamento.
Rest API: Acessar tweets antigos.
O Twitter possui duas API: Rest API e Stream API. Vamos começar com a REST API. Esta API permite:
Acesso a tweets dos últimos 6-9 dias.
18.000 tweets em cada acesso de 15 minutos.
Para usar esta função, você precisa entrar um termo de busca. A busca avançada no Twitter ajuda a formatar os termos de busca adequados quando seu interesse está em mais de uma simples palavras.
bolsonaro_tweets<-search_tweets("bolsonaro", n=50, include_rts = TRUE)
# Checa se vieram retuites
bolsonaro_tweets$is_retweet
Vamos entender as informações deste banco de dados.
# Simple View
bolsonaro_tweets
# Glimpse
colnames(bolsonaro_tweets)
Muita informação. Mais do que eu posso pensar em diferentes formas de analisar.
Acessar Timelines
Esta função permite acessar os últimos 3.200 tweets a partir dos perfis.
# Tweets dos membros da CPI do COVID.
timelines_covid <- get_timelines(c("renancalheiros", "ottoalencar", "EduGiraoOficial"), n=100)
Acessar informações de usuários
Ou podemos acessar informações específicas de determinados usuários.
users <-lookup_users(c("renancalheiros", "ottoalencar", "EduGiraoOficial"))
# descrição do perfil
users$description
Ou acessar os tweets que estes deputados recentemente deram um like.
favs <- get_favorites(c("renancalheiros", "ottoalencar", "EduGiraoOficial"))
E seguidores
follow_renan <- get_followers("renancalheiros")
E com a id dos seguidores, podemos montar um banco com a descrição dos seguidores de Renan Calheiros.
followers_renan <- lookup_users(follow_renan$user_id)
followers_renan %>%
slice(1:10) %>%
pull(description)
API Stream
O Twitter possui uma segunda API onde você pode coletar uma amostra dos tweets sendo produzidos em tempo real. Esta API lhe dá mais acesso a dados, então é a melhor forma de coletar, você pode deixar algumas horas – ou dias – rodando no seu R.
dados_bolsonaro_stream <- stream_tweets("bolsonaro",
timeout = 10,
file_name = "bolsonaro.json") # adicione o tempo que voce quer coletar
Análise de Redes.
Pensando em Redes
Há milhões de formas de análisar dados de twitter. Porém, um dos elementos centrais em plataformas como estas é o fato dos usuários interagirem entre si. Portanto, estes usuários se conectam em redes.
Uma rede possui dois elementos básicos: um nó - usuário - e um link - que iremos considerar um retweet. Para construir nossa rede, vamos selecionar usuários a partir dos seus retuítes. Esta é a forma mais básica de análise de redes do Twitter, e com isto vamos replicar alguns resultados do artigo do “Time to Protest” de Calvo e Aruguete.
Para construir a rede de conexões, vamos usar o pacote igraph
. Este pacote armazena dados de forma um tanto distinta, porém, é a forma mais intuitiva de manipular dados de rede em R.
# Buscando mais dados
?search_tweets
dados_bolsonaro <- search_tweets("bolsonaro filter:retweets", n=18000,
include_rts = TRUE,
retryonratelimit = TRUE)
dados_bolsonaro
Construíndo uma rede
Passo 1: Selecione os nós – Autoridades -> Hub
Autoridades: Autor do Tweet <-
Hub: Autor do Retweet ->
# Segura somente retuite
library(tidyverse)
dados_bolsonaro_rt <- dados_bolsonaro %>%
filter(is_retweet==TRUE)
# Criar uma edgelist = lista de conexoes da sua rede
data <- cbind(dados_bolsonaro_rt$screen_name, dados_bolsonaro_rt$retweet_screen_name)
head(data)
Passo 2: Crie a estrutura da rede
library(igraph)
# Cria um gráfico vazio
net <- graph.empty()
# Adiciona os nós = vertices
net <- add.vertices(net,
length(unique(c(data))), # número de nós
name=as.character(unique(c(data)))) # nomes unicos
net <- add.edges(net, t(data))
# Ou
g <- graph_from_data_frame(d=data, vertices=unique(c(data)))
summary(g)
summary(net)
Passo 3: Adicione as variáveis
E(net)$text <- dados_bolsonaro_rt$text
E(net)$nameauth <- dados_bolsonaro_rt$screen_name
E(net)$namehub <- dados_bolsonaro_rt$retweet_screen_name
E(net)$web <- dados_bolsonaro_rt$urls_expanded_url
E(net)$hash <- dados_bolsonaro_rt$hashtags
summary(net)
Estatística de Rede, Comunidades e Layout.
Vamos usar aqui o conceito de in-degree e out-degree. In-degree significa quantos links direcionados a si o usuário possui. Portanto, em nosso caso mostra quantos retweets este usuário recebeu. O oposto explica out-degree. Neste caso, out-degree significa quantos retuites o usuario deu.
Um usuário é chamado de autoridade quando seu in-degree é alto. Ou seja, muitos usuários o-a retuítam. Chamamos de hub quando seu out-degree é alto, pois este usuário retuíta muito frequentemente. Os robôs do Bolsonaro são, portanto, hubs – ninguém retuíta eles, eles somente retuítam muito, e muito rápido.
# Adicionar indegree and outdegree
V(net)$outdegree<-degree(net, mode="out")
V(net)$indegree<-degree(net, mode="in")
Layout
Estima posições para os nós da sua rede, é um algoritimo que organiza a topologia das rede de conexões
l <- layout_with_fr(net, grid = c("nogrid"))
head(l)
Comunidades
Há vários algorítimos para encontrar comunidades (ou clusters) em sua rede. Estes algorítimos em geral buscam subgrupos com mais conexões dentro da sua rede. Não vamos entrar numa discussão detalhada sobre os diferentes algorítimos. Ao final, os resultados são semelhantes.
my.com.fast <- walktrap.community(net)
Adicionando o layout a sua rede
V(net)$l1 <- l[,1]
V(net)$l2 <- l[,2]
my.com.fast$membership
V(net)$membership <- my.com.fast$membership
Quais as maiores comunidades?
comunidades<- data_frame(membership=V(net)$membership)
comunidades %>%
count(membership) %>%
arrange(desc(n)) %>%
top_n(5)
Quem são os mais influentes em cada comunidade?
Para medir as autoridades de cada comunidades, irei primeiro selecionar as principais autoridades por comunidade. Em seguida, plotaremos quem são esses usuários, e quantos retuítes receberam neste período pré-eleição.
# Cria um banco com indegree
autoridade <- data_frame(name=V(net)$name, ind=V(net)$indegree,
membership=V(net)$membership) %>%
filter(membership==1| membership==2) %>%
split(.$membership) %>%
map(~ arrange(., desc(ind))) %>%
map(~ slice(., 1:30))
# Comunidade 1
ggplot(autoridade[[1]], aes(x=reorder(name,
ind),
y=ind)) +
geom_histogram(stat="identity", width=.5, color="black",
fill="darkred") +
coord_flip() +
xlab("") + ylab("") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(size = 22, face = "bold"),
axis.title=element_text(size=16),
axis.text = element_text(size=12, face="bold"))
# Comunidade 2
ggplot(autoridade[[2]], aes(x=reorder(name,
ind),
y=ind)) +
geom_histogram(stat="identity", width=.5, color="black",
fill="yellow") +
coord_flip() +
xlab("") + ylab("") +
theme_minimal(base_size = 12) +
theme(plot.title = element_text(size = 22, face = "bold"),
axis.title=element_text(size=16),
axis.text = element_text(size=12, face="bold"))
Visualizar Comunidades
Há muitos pacotes distintos para visualização de dados em rede em R. Este tutorial aqui cobre as principais opções. Vou apresentar a opção mais simples que vem diretamente do igraph
. Um outro caminho é utilizar extensões do ggplot, como o ggnet e o ggraph. O problemas das extensões do ggplot é que você precisa converter o objeto igraph para banco de dados, e este processo tende a ser lento e gerar alguns erros.
# plot igraph
plot.igraph(net,
layout=cbind(V(net)$l2,V(net)$l1),
vertex.size=log(V(net)$indegree),
vertex.label.color=1,
vertex.label=NA,
vertex.color=V(net)$membership,
vertex.frame.color=gray(.8),
edge.color=gray(.8),
edge.arrow.size=.2,
edge.curved=TRUE)
# Ou esta outra opção mais manual.
# Funcao para visualizar a rede
my.den.plot <- function(l=l,new.color=new.color, ind=ind, legend){
library(KernSmooth)
#Numero efectivo de Comunidades
# ENCG<-round(1/sum(round(table(new.color)/sum(table(new.color)),3)^2),2)
#
est <- bkde2D(l, bandwidth=c(10, 10))
plot(l,cex=log(ind+1)/4, col=new.color, pch=16, xlim=c(-160,140),ylim=c(-140,120), xlab="", ylab="", axes=FALSE)
contour(est$x1, est$x2, est$fhat, col = gray(.6), add=TRUE)
legend("topright", c(legend[2],legend[1]), pch = 17:18, col=c("#B2182B", "#2166AC"))
#text(-140,115,paste("ENCG: ",ENCG,sep=""), cex=1, srt=0)
}
# Crie as cores para cada comunidade
# Building a empty containes
temp <- rep(1,length(V(net)$membership))
new.color <- "white"
new.color[V(net)$membership==2] <- "red" ####
new.color[V(net)$membership==1] <- "blue" ####
# Adiciona a nova cor
V(net)$new.color <- new.color
# Plot
#save first
my.den.plot(l=cbind(V(net)$l1,V(net)$l2),new.color=V(net)$new.color, ind=V(net)$indegre, legend =c("Pro-Bolsonaro", "Anti-Bolsonaro"))
Analizando ativação das mídias na rede
Um dos argumentos do artigo que lemos de Aruguete e Calvo é sobre como ativação de conteúdo ocorre em redes no twitter. Em outras palavras, comunidades diferentes reagem e falam sobre o mesmo assunto de formas distintas. Para visualizar isto, vamos fazer um gráfico de redes para cada uma das hashtags e verificar em quais áreas das redes essas hashtags são ativadas
Este código abaixo foi criado por um dos autores do artigo, Ernesto Calvo. Portanto, vocês vão notar como o código usa mais R básico do que eu costumo. Nesse caso, o código fica bem mais eficiente deste jeito – tidyverse não funciona muito bem para redes.
Contando o número de menções por nó.
summary(net)
# Vamos primeiro selecionar as mídias mais ativadas
keynews <- head(sort(table(unlist(E(net)$hash)),decreasing=TRUE),12)
keynews.names <- names(keynews)
N<-length(keynews.names)
count.keynews<- array(0,dim=c(length(E(net)),N))
str(count.keynews)
# Looping
for(i in 1:N){
temp<- grepl(keynews.names[i], E(net)$hash, ignore.case = TRUE)
#temp <- str_match(E(net)$text,'Arangur[A-Za-z]+[A-Za-z0-9_]+')
count.keynews[temp==TRUE,i]<-1
Sys.sleep(0.1)
}
# Setting the names of the media
colnames(count.keynews)<- keynews.names
Recuperando a matrix de vizinhança da rede.
# Conexoes de Vertices e Edges
# Vamos recuperar todos os nós e edges que estão ligados uns com os outros.
el <- get.adjedgelist(net, mode="all")
al <- get.adjlist(net, mode="all")
Função para verificar activação na rede
# Função para detectar ativação entre as conexões em rede.
fomfE<- function(var=var, adjV=adjV,adjE=adjE){
stemp <- map_dbl(adjE, function(x) sum(var[x]))
#mstemp <- sapply(adjV, function(x) mean(stemp[x]))
out<-cbind(stemp)
}
# Cria um container
resultado_hash<- array(0,dim=c(length(V(net)),N))
# Repita para cada uma das hashtags
for(i in 1:N){
bb<-fomfE(count.keynews[,i],al,el)
bb[bb[,1]=="NaN"]<-0
resultado_hash[,i]<- bb[,1]
}
class(resultado_hash)
colnames(resultado_hash)<- keynews.names
Visualizando Gráficos de Ativação
Você pode facilmente fazer um por um. Porém, escrevi um loop curtinho para plotar eles juntos.
# all
my.den.plot(l=cbind(V(net)$l1,V(net)$l2),new.color=V(net)$new.color, ind=V(net)$indegre, legend =c("Bolsonaro", "Anti-Bolsonaro"))
# CPI COVID
plot(V(net)$l1,V(net)$l2,pch=16,
col=V(net)$new.color, cex=log(resultado_hash[,1]+1),
xlim=c(-160,140),ylim=c(-140,120), xlab="", ylab="",
main=colnames(resultado_hash)[1], cex.main=1)
# Mandetta Genocida
plot(V(net)$l1,V(net)$l2,pch=16,
col=V(net)$new.color, cex=log(resultado_hash[,5]+1),
xlim=c(-160,140),ylim=c(-140,120), xlab="", ylab="",
main=colnames(resultado_hash)[5], cex.main=1)
save.image(file="aula_twitter.RData")
getwd()