First I will load required packages:
library(tidyverse)
library(DT)
library(igraph)
library(rtweet)
library(visNetwork)
library(graphTweets) # This package turns twitter data into edge & node data
Now I will authenticate to the Twitter API.
get_token() # this shows the token. make sure key is the same as consumer_key above
<Token>
<oauth_endpoint>
request: https://api.twitter.com/oauth/request_token
authorize: https://api.twitter.com/oauth/authenticate
access: https://api.twitter.com/oauth/access_token
<oauth_app> RTweets for PSYC 541
key: 9z2JeDsn0047F1W96VWxZCEVV
secret: <hidden>
<credentials> oauth_token, oauth_token_secret
---
- I want to look at the re-tweet networks of US senators, so first I will tell R to pull up the most recent 200 tweets from them.
senate <- lists_members(slug = "us-senate", owner_user = "TwitterGov")
senate_tweets <- get_timeline(senate$screen_name, n = 200)
Rate limit exceeded - 88rate limit exceeded. mins until rate limit resets.Rate limit exceeded - 88rate limit exceeded. mins until rate limit resets.Rate limit exceeded - 88rate limit exceeded. mins until rate limit resets.Rate limit exceeded - 88rate limit exceeded. mins until rate limit resets.
- The blocks of R code below cumulatively result in the appearance of a visual representation of a network of retweets.
# This creates the network with some commands from graphTweets
# The variables in the parentheses of gt_edges() are used, so in this case we're using retweets
senate_retweets_network <- senate_tweets %>%
filter(retweet_screen_name %in% senate$screen_name) %>% # <- This is a new line and important.
gt_edges(screen_name, retweet_screen_name, text) %>% # It only keep retweets of other cabinet members
gt_graph()
# This next line gets the nodes
senate_retweets_nodes <- as_data_frame(senate_retweets_network, what = "vertices")
# This adds some additional info to the nodes, so we get the names on hover
# and the size of the node is based on its degree, etc.
senate_retweets_nodes <- senate_retweets_nodes %>%
mutate(id = name) %>%
mutate(label = name) %>%
mutate(title = name) %>%
mutate(degree = degree(senate_retweets_network)) %>%
mutate(value = degree)
# This gets the edges, similar to how we got the nodes above
senate_retweets_edges <- as_data_frame(senate_retweets_network, what = "edges")
# This puts the text of the tweet itself into the edge
# so when you hover over a line in the diagram it will show the tweet
senate_retweets_edges <- senate_retweets_edges %>%
mutate(title = text)
# Creates the diagram
visNetwork(senate_retweets_nodes, senate_retweets_edges, main = "US senate officials retweet network") %>%
visIgraphLayout(layout = "layout_nicely") %>%
visEdges(arrows = "to")
- Now I would like to see how many nodes/vertices (in this case, each reprsenting a senator engaging in retweeting activity). I would also like to see how many edges there are (in this case representing the actual number of retweets within the network). Finally, I would like to know the density of the network. The R code below does all of these things.
senate_retweet_network %>%
vcount()
senate_retweet_network %>%
ecount()
senate_retweet_network %>%
edge_density()
- I also want to tell R to present a data table showing senator names and degrees.
senate_mentions_nodes %>%
select(name, degree) %>%
datatable()
- Finally, I want to see what kind of communities emerge when analyzing the network. The R code below finds the communities in the data and then displays an interactive diagram so that we can explore this further.
senate_retweets_nodes <- senate_retweets_nodes %>%
mutate(group = membership(infomap.community(senate_retweets_network)))
visNetwork(senate_retweets_nodes, senate_retweets_edges, main = "US senate officials retweet network") %>%
visIgraphLayout(layout = "layout_nicely") %>%
visEdges(arrows = "to") %>%
visOptions(highlightNearest = T, nodesIdSelection = T, selectedBy = "group")
LS0tCnRpdGxlOiAiVHdpdHRlciBuZXR3b3JrcyIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKRmlyc3QgSSB3aWxsIGxvYWQgcmVxdWlyZWQgcGFja2FnZXM6CgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoRFQpCmxpYnJhcnkoaWdyYXBoKQpsaWJyYXJ5KHJ0d2VldCkKbGlicmFyeSh2aXNOZXR3b3JrKQpsaWJyYXJ5KGdyYXBoVHdlZXRzKSAgICAgICAgICAgICMgVGhpcyBwYWNrYWdlIHR1cm5zIHR3aXR0ZXIgZGF0YSBpbnRvIGVkZ2UgJiBub2RlIGRhdGEKCmBgYAoKCk5vdyBJIHdpbGwgYXV0aGVudGljYXRlIHRvIHRoZSBUd2l0dGVyIEFQSS4gCgoKYGBge3J9CmdldF90b2tlbigpICAgICAgICAjIHRoaXMgc2hvd3MgdGhlIHRva2VuLiBtYWtlIHN1cmUga2V5IGlzIHRoZSBzYW1lIGFzIGNvbnN1bWVyX2tleSBhYm92ZQpgYGAKCjEuIEkgd2FudCB0byBsb29rIGF0IHRoZSByZS10d2VldCBuZXR3b3JrcyBvZiBVUyBzZW5hdG9ycywgc28gZmlyc3QgSSB3aWxsIHRlbGwgUiB0byBwdWxsIHVwIHRoZSBtb3N0IHJlY2VudCAyMDAgdHdlZXRzIGZyb20gdGhlbS4gCgpgYGB7cn0Kc2VuYXRlIDwtIGxpc3RzX21lbWJlcnMoc2x1ZyA9ICJ1cy1zZW5hdGUiLCBvd25lcl91c2VyID0gIlR3aXR0ZXJHb3YiKQoKc2VuYXRlX3R3ZWV0cyA8LSBnZXRfdGltZWxpbmUoc2VuYXRlJHNjcmVlbl9uYW1lLCBuID0gMjAwKQoKYGBgCgoKMi4gVGhlIGJsb2NrcyBvZiBSIGNvZGUgYmVsb3cgY3VtdWxhdGl2ZWx5IHJlc3VsdCBpbiB0aGUgYXBwZWFyYW5jZSBvZiBhIHZpc3VhbCByZXByZXNlbnRhdGlvbiBvZiBhIG5ldHdvcmsgb2YgcmV0d2VldHMuICAKCmBgYHtyfQojIFRoaXMgY3JlYXRlcyB0aGUgbmV0d29yayB3aXRoIHNvbWUgY29tbWFuZHMgZnJvbSBncmFwaFR3ZWV0cwojIFRoZSB2YXJpYWJsZXMgaW4gdGhlIHBhcmVudGhlc2VzIG9mIGd0X2VkZ2VzKCkgYXJlIHVzZWQsIHNvIGluIHRoaXMgY2FzZSB3ZSdyZSB1c2luZyByZXR3ZWV0cwpzZW5hdGVfcmV0d2VldHNfbmV0d29yayA8LSBzZW5hdGVfdHdlZXRzICU+JSAKICBmaWx0ZXIocmV0d2VldF9zY3JlZW5fbmFtZSAlaW4lIHNlbmF0ZSRzY3JlZW5fbmFtZSkgJT4lICAgICAjIDwtIFRoaXMgaXMgYSBuZXcgbGluZSBhbmQgaW1wb3J0YW50LgogIGd0X2VkZ2VzKHNjcmVlbl9uYW1lLCByZXR3ZWV0X3NjcmVlbl9uYW1lLCB0ZXh0KSAlPiUgICAgICAgICAgICAgIyBJdCBvbmx5IGtlZXAgcmV0d2VldHMgb2Ygb3RoZXIgY2FiaW5ldCBtZW1iZXJzCiAgZ3RfZ3JhcGgoKQoKCiMgVGhpcyBuZXh0IGxpbmUgZ2V0cyB0aGUgbm9kZXMKc2VuYXRlX3JldHdlZXRzX25vZGVzIDwtIGFzX2RhdGFfZnJhbWUoc2VuYXRlX3JldHdlZXRzX25ldHdvcmssIHdoYXQgPSAidmVydGljZXMiKQoKIyBUaGlzIGFkZHMgc29tZSBhZGRpdGlvbmFsIGluZm8gdG8gdGhlIG5vZGVzLCBzbyB3ZSBnZXQgdGhlIG5hbWVzIG9uIGhvdmVyCiMgYW5kIHRoZSBzaXplIG9mIHRoZSBub2RlIGlzIGJhc2VkIG9uIGl0cyBkZWdyZWUsIGV0Yy4Kc2VuYXRlX3JldHdlZXRzX25vZGVzIDwtIHNlbmF0ZV9yZXR3ZWV0c19ub2RlcyAlPiUgCiAgbXV0YXRlKGlkID0gbmFtZSkgJT4lIAogIG11dGF0ZShsYWJlbCA9IG5hbWUpICU+JSAKICBtdXRhdGUodGl0bGUgPSBuYW1lKSAlPiUgCiAgbXV0YXRlKGRlZ3JlZSA9IGRlZ3JlZShzZW5hdGVfcmV0d2VldHNfbmV0d29yaykpICU+JSAKICBtdXRhdGUodmFsdWUgPSBkZWdyZWUpCgojIFRoaXMgZ2V0cyB0aGUgZWRnZXMsIHNpbWlsYXIgdG8gaG93IHdlIGdvdCB0aGUgbm9kZXMgYWJvdmUKc2VuYXRlX3JldHdlZXRzX2VkZ2VzIDwtIGFzX2RhdGFfZnJhbWUoc2VuYXRlX3JldHdlZXRzX25ldHdvcmssIHdoYXQgPSAiZWRnZXMiKQoKIyBUaGlzIHB1dHMgdGhlIHRleHQgb2YgdGhlIHR3ZWV0IGl0c2VsZiBpbnRvIHRoZSBlZGdlCiMgc28gd2hlbiB5b3UgaG92ZXIgb3ZlciBhIGxpbmUgaW4gdGhlIGRpYWdyYW0gaXQgd2lsbCBzaG93IHRoZSB0d2VldApzZW5hdGVfcmV0d2VldHNfZWRnZXMgPC0gc2VuYXRlX3JldHdlZXRzX2VkZ2VzICU+JSAKICBtdXRhdGUodGl0bGUgPSB0ZXh0KQoKIyBDcmVhdGVzIHRoZSBkaWFncmFtCnZpc05ldHdvcmsoc2VuYXRlX3JldHdlZXRzX25vZGVzLCBzZW5hdGVfcmV0d2VldHNfZWRnZXMsIG1haW4gPSAiVVMgc2VuYXRlIG9mZmljaWFscyByZXR3ZWV0IG5ldHdvcmsiKSAlPiUgCiAgdmlzSWdyYXBoTGF5b3V0KGxheW91dCA9ICJsYXlvdXRfbmljZWx5IikgJT4lIAogIHZpc0VkZ2VzKGFycm93cyA9ICJ0byIpCmBgYAoKMy4gTm93IEkgd291bGQgbGlrZSB0byBzZWUgaG93IG1hbnkgbm9kZXMvdmVydGljZXMgKGluIHRoaXMgY2FzZSwgZWFjaCByZXByc2VudGluZyBhIHNlbmF0b3IgZW5nYWdpbmcgaW4gcmV0d2VldGluZyBhY3Rpdml0eSkuIEkgd291bGQgYWxzbyBsaWtlIHRvIHNlZSBob3cgbWFueSBlZGdlcyB0aGVyZSBhcmUgKGluIHRoaXMgY2FzZSByZXByZXNlbnRpbmcgdGhlIGFjdHVhbCBudW1iZXIgb2YgcmV0d2VldHMgd2l0aGluIHRoZSBuZXR3b3JrKS4gRmluYWxseSwgSSB3b3VsZCBsaWtlIHRvIGtub3cgdGhlIGRlbnNpdHkgb2YgdGhlIG5ldHdvcmsuIFRoZSBSIGNvZGUgYmVsb3cgZG9lcyBhbGwgb2YgdGhlc2UgdGhpbmdzLgoKYGBge3J9CnNlbmF0ZV9yZXR3ZWV0X25ldHdvcmsgJT4lIAogIHZjb3VudCgpCmBgYAoKYGBge3J9CnNlbmF0ZV9yZXR3ZWV0X25ldHdvcmsgJT4lCiAgZWNvdW50KCkKYGBgCgpgYGB7cn0Kc2VuYXRlX3JldHdlZXRfbmV0d29yayAlPiUKICBlZGdlX2RlbnNpdHkoKQpgYGAKCjQuIEkgYWxzbyB3YW50IHRvIHRlbGwgUiB0byBwcmVzZW50IGEgZGF0YSB0YWJsZSBzaG93aW5nIHNlbmF0b3IgbmFtZXMgYW5kIGRlZ3JlZXMuIAoKYGBge3J9CnNlbmF0ZV9tZW50aW9uc19ub2RlcyAlPiUKICBzZWxlY3QobmFtZSwgZGVncmVlKSAlPiUKICBkYXRhdGFibGUoKQpgYGAKCjUuIEZpbmFsbHksIEkgd2FudCB0byBzZWUgd2hhdCBraW5kIG9mIGNvbW11bml0aWVzIGVtZXJnZSB3aGVuIGFuYWx5emluZyB0aGUgbmV0d29yay4gVGhlIFIgY29kZSBiZWxvdyBmaW5kcyB0aGUgY29tbXVuaXRpZXMgaW4gdGhlIGRhdGEgYW5kIHRoZW4gZGlzcGxheXMgYW4gaW50ZXJhY3RpdmUgZGlhZ3JhbSBzbyB0aGF0IHdlIGNhbiBleHBsb3JlIHRoaXMgZnVydGhlci4gCgpgYGB7cn0Kc2VuYXRlX3JldHdlZXRzX25vZGVzIDwtIHNlbmF0ZV9yZXR3ZWV0c19ub2RlcyAlPiUgCiAgbXV0YXRlKGdyb3VwID0gbWVtYmVyc2hpcChpbmZvbWFwLmNvbW11bml0eShzZW5hdGVfcmV0d2VldHNfbmV0d29yaykpKQoKdmlzTmV0d29yayhzZW5hdGVfcmV0d2VldHNfbm9kZXMsIHNlbmF0ZV9yZXR3ZWV0c19lZGdlcywgbWFpbiA9ICJVUyBzZW5hdGUgb2ZmaWNpYWxzIHJldHdlZXQgbmV0d29yayIpICU+JSAKICB2aXNJZ3JhcGhMYXlvdXQobGF5b3V0ID0gImxheW91dF9uaWNlbHkiKSAlPiUgCiAgdmlzRWRnZXMoYXJyb3dzID0gInRvIikgJT4lICAgCiAgdmlzT3B0aW9ucyhoaWdobGlnaHROZWFyZXN0ID0gVCwgbm9kZXNJZFNlbGVjdGlvbiA9IFQsIHNlbGVjdGVkQnkgPSAiZ3JvdXAiKQoKCmBgYAo=