Demo: Networks from Real Data

Networks from real data

First off, what directory are we in?

Directory[]

I have a data file!

I really really like League of Legends. It’s an online competitive video game. The game developers have their own “restful” API (RESTful is just a standardized API) for collecting any amount of data on the video game... for free! But you do need to make an account to get the data. Check it out here: https://developer.riotgames.com/
Anyways, I downloaded data from the API through Python and then transformed the data into a network. I saved the network into a JSON file.

Here’s how I structured the network: Character A ---> Character B Means that A won a game against B. The weight means the number of games where A beat B. This network has parallel edges that go in opposite directions, meaning edges A-->B and B-->A can both exist, each with their own edge weight. There are 140+ nodes in this network and one full month worth of games for 200 players in North America (only the best 200 players on the server!).

I only collected the data and made a network, I know nothing about it!

Let’s see if we can load the file here:

json=Import["PycharmProjects/League/network_demo.json"]

Hm... We need to get this into a format Mathematica will like!

If you’re a data engineer, this is what you do! ;)

Let’s look at the Graph function to see what kinds of formats it accepts.

Graph

It would be easiest to made an edge list like with the CAs above. We can put the weights in there as well, as long as we preserve the order of the edges.
It looks like we can get all of this information from the “links ->” part of the file.

links = Lookup[json,"links"]

Let’s get rid of those arrows.

links=Values/@links

That is a nice list! It is a list of lists. For each of the lists in the list, we can make an edge list by taking the second and third element. How can we easily take them? By making a special function! But this time we are going to do it in shorthand. In this format, the # is the variable, the & activates it, and /@ means “apply it to all the elements in this list”.

edges=#[[2]]->#[[3]]&/@links

To get the weights, we can just take the first element. Easy!

weights=First/@links

Excellent! We are now ready to plot our graph..... or.... are we? See how there are more than 18K edges. Ouch. I hope this doesn’t break my laptop.

biggraph = Graph[edges, EdgeWeight->weights]

Gross. Well, it doesn’t really look like anything so it’s difficult to get any information out of looking at it. Instead, it would be much easier to apply some measures to gain a sense of what is happening!

Let’s blast it with measures!

In the documentation, you can search “graph properties and measurements” and a whole bunch of things will pop up.

VertexCount[biggraph]
EdgeCount[biggraph]

VertexDegree[biggraph]
VertexList[biggraph]
SortBy[Transpose[{VertexList[biggraph],VertexDegree[biggraph]}],Last]

So many things we could explore, so let’s focus on a game-centric aspect. 
Since A-->B means that character A beat character B, character A would be really a really good character to play if it a ton of out-degrees and very little in-degrees! Let’s explore this idea a little bit.
First, what is the distribution of all degrees? In degree and out degrees together? Separate?

ListPlot[VertexDegree[biggraph]//Sort, PlotLabel->"Degree Distribution, Sorted"]

The x-axis doesn’t matter here since the numbers are just labels for characters.

ListPlot[VertexInDegree[biggraph]//Sort, PlotLabel->"In-Degree Distribution, Sorted"]

ListPlot[VertexOutDegree[biggraph]//Sort, PlotLabel->"Out-Degree Distribution, Sorted"]

It looks like, for the most part, the majority of characters have similar in-degree and out-degree, except for a small handful of characters. Perhaps these characters are unpopular or something. Let’s see the ratio of out-degree and in-degree. A high ratio indicates a character beats more characters than loses against more characters.

ListPlot[(VertexOutDegree[biggraph]/VertexInDegree[biggraph])//Sort, PlotLabel->"Out/In Degree Distribution, Sorted"]

Whoa! That looks really cool! Those characters on the right must be really good, and the ones on the left must be really bad...
However, it may not be actually be reflective of our intuition since there are edge weights. Some edges are really heavy, meaning there may A-->B for a TON of matches and B-->A for only one or two matches. The edges are not equal! Let’s see if there are measures that take edge weight into account. Also A-->B edges and A-->C edges can have different weights too.

Back to the guide!

EigenvectorCentrality is a really good one to use. It’s a lot like Page Rank. Basically, it means that if someone is connected a LOT to a bunch of other people, it has a higher value. But it has an even HIGHER value if all the nodes are connected to have a high value! Intuitively, it means you’re more popular if you have lots of popular friends.

ListPlot[EigenvectorCentrality[biggraph, "In"]//Sort, PlotLabel->"EVC (In-degrees), Sorted"]

ListPlot[EigenvectorCentrality[biggraph, "Out"]//Sort, PlotLabel->"EVC (Out-degrees), Sorted"]

ListPlot[(EigenvectorCentrality[biggraph, "Out"]/EigenvectorCentrality[biggraph, "In"])//Sort, PlotLabel->"EVC (Out/In degrees), Sorted"]

Most excellent! Now we can, with a higher degree of confidence, say that these make intuitive sense.