Creating Beautiful Twitter Graphs with Python | by Sean Whalen | Towards Data Science

Want to learn two useful Python packages? Want to visualize everyone who doesn’t follow you back on Twitter in one bitter and pathetic graph? Read on.
Graphs in the programming sense are a collection of vertices and edges, rather than a bar graph or a scatter-plot — but you knew that already. Graphs are powerful tools that have the potential to communicate complex relationships visually. Plus, they can be pretty. Why not see what relationships we can deduce from Twitter?
Twitter already has a Python API, python-twitter, so we don’t have to make HTTP requests and parse responses ourselves. We will have to create some app-credentials through Twitter in order to use it. I found this a fairly painless process, so I’m simply going to refer you to python-twitter’s excellent guide on how to do this. All you need is a Twitter account, no special privileges necessary.
With our credentials in hand we can create an instance of the Twitter API and set to work.
I’m an NBA fan so for this demonstration I’m going to graph player-to-player connections on Twitter. This a fun dataset because the league has a very active social media presence and there are easily obtainable attributes per player, such as contract size, team, and position. You could follow the same steps for whatever Twitter users you’re interested in, whether it be celebrity chefs, musical artists, or #QAnon posters.
There are 30 NBA teams with around 15 players each. I wasn’t keen on manually looking up 450 Twitter handles to feed them into the API, especially if I could do it programmatically. Basketball-reference.com came to my rescue. Below I found a table of all the players under contract for the 2018–19 season.
www.basketball-reference.com
Armed with this list of player names I used the API to search for the corresponding Twitter-ids and bundled all the attributes per player together in a vertex list dubbed V. If you already had a list of screen names or Twitter-ids this would be redundant, but in case you don’t here’s the code:
After all that V will be a list-of-lists, which I dumped as a .csv file with the columns |TWITTER ID|USER NAME|SCREEN NAME|TEAM.
nba_verts.csv42562446,Stephen Curry,StephenCurry30, GSW53853197,Chris Paul,CP3, HOU23083404,LeBron James,KingJames, LAL...
I knew I was looking for high-profile athletes, so I only included users in my search that were verified and assumed that the first result from the search was the correct one — which turned out not always to be true. Finally, I iterated over V and used the GetFriendIDs() API call to find the friends of each Twitter-id. A friend is a person a user is following. If the friend was in V, a condition I checked with a dictionary, I output this edge to another .csv file.
nba_edges.csv42562446,5364329742562446,5929723342562446,2806643642562446,4670424742562446,34430522...
A graph is a collection of vertices and edges and now we have both; we’re ready to do our viz.
At this point you could simply load your vertex and edge list into your favorite graph plotting software (mine is cytoscape) and go from there....but that wouldn’t be any fun. Let’s see what we can do strictly sticking to Python.
Python-igraph was my package of choice. It has quite a few dependencies, and may not be as smooth to install as its R implementation, but it is well maintained and very powerful once you get the hang of its syntax. I found it easiest to install with Python 2.7 and easiest to use inside a Jupyter Notebook.
Let’s make a graph from our edges and vertices. For demonstration’s sake I’ll only include the top 10 highest paid players.
from igraph import *#this info read in from our .csv filesE          = [("42562446","53643297"), ("42562446","59297233"),...]V          = ["42562446", "53853197", "23083404",...]user_names = ["Stephen Curry", "Chris Paul", "LeBron James",...]scrn_names = ["StephenCurry30", "CP3", "KingJames",...]g = Graph(directed=True)g.add_vertices(V)g.add_edges(E)plot(g)
That plot() would produce this beauty:
Oh my. What the heck is going on? What vertex is what Twitter user? And why is it SO HAIRY?
Don’t worry, we’re going to apply some styling to fix all of this.
For starters let’s add some labels. Then we can straighten out the hairball by removing the curved edges, and add a margin to safeguard labels from drifting outside the bounding box. We’ll keep our styling decisions in a dictionary called style so we can reuse it later.
#add vertex attributesg.vs["screen_name"] = scrn_namesg.vs["user_name"] = user_namesstyle = {}style["edge_curved"] = Falsestyle["margin"] = 100style["vertex_label"] = g.vs["user_name"]plot(g, **style)
We use the .vs member of the graph to associate an attribute with the vertices, with an attribute-value for each vertex mapped in the order the vertices were added. Since our user_name and scrn_name arrays were parallel with V, it’s a pretty simple process.
This already looks okay, but one of my goals for the viz was to efficiently communicate what a follow was versus a follow-and-a-follow-back. With igraph it’s easy to iterate over the edges and detect these cases and change edge styling according.
for e in g.es:    src, targ = e.tuple    if g.are_connected(targ, src):        e["color"] = "green"           #follow + followback        e["arrow_size"] = 0                           else:        e["color"] = "blue"            #follow        e["arrow_size"] = 1plot(g, **style)
Well there you have it folks, LeBron has left Kyle Lowry of the Toronto Raptors and Gordon Hayward of the Boston Celtics hanging. Come on LeBron!
From here you could style the vertices so they don’t conflict so much with the labels, adjust the label distance from the vertices, experiment with different layouts (how the graph is structured), and much much more. I’d suggest saving your plot as an .svg file so you can get your labels or vertices arranged exactly right with an editor like Inkscape.
The 30 NBA team graphs shown from the beginning of this article used a circular graph layout with colors from each team’s official palette (igraph supports hex code coloring). Here’s the one for my favorite team, the Golden State Warriors, up close:
Not only is this pleasing to the eye, but it does give us some insight about the relationships between players. Curry and Green seem to be the most connected overall and generous in following back. Thompson, Durant and Livingston are a little more aloof having more unreturned follows. Demarcus Cousins, a recent pickup, has already made an effort to follow his new teammates (...or already followed them).
You could take things a step further and employ the vast array of graph algorithms built into igraph and to answer questions like:
What player in the NBA is the most central?
Who has the best followers-following differential?
What cliques exist in the NBA?
What team has the highest density (of edges), what team has the lowest?
I’ll be refactoring and updating my code sporadically on GitHub, but the gist of what I’ve demonstrated is there already, as well as the full NBA graph.
I anxiously await what beautiful graphs you create from Twitter! I’d love it if you shared them with me.