Appendix B — Interactive Network Visualization

library(igraph)
library(intronets)
library(threejs) # 3D Networks
library(visNetwork) # Interactive
library(htmlwidgets) 
library(htmltools)
library(dplyr)

In this chapter we will learn about how to create engaging network visualisations. By engaging, we mean so literally. One way to help your audience understand a network is to have them interact with it. R offers multiple different packages all filled with fun ways to accomplish this. In this chapter, we cover 2 methods one that creates 3D networks and a second that creates interactive networks.

B.1 The Data

To do this, we are going to use the terrorism data (Koschade 2006; Magouirk, Atran & Sageman 2008) that we used in our chapter on graph layouts. Just a quick refresher on this network, it was constructed based on the Jemaah Islamiyah cell that was responsible for the 2002 bombings in Bali. Ties are constructed through interactions between individuals within the terror organization. The roles are recorded for each individual as bomb maker (BM), command team (CT), operation assistant (OA), team lima (TL), and suicide bombers (SB). Below we read in the data and explore it a little.

load_nets("bali.rda")

B.2 3D Networks with threejs

If you are working with other data, you will need to create an igraph object from the edgelist or adjacency matrix. Once you have an igraph network object you can then create your 3D network.

To create the 3D Network we use the grpahjs() function which simply converts your static igraph object into an engaging model. In this visualization you can scroll in and out to zoom and click and drag to move around the network. It places the network in a spherical shape in the plot window and allows you to move in, out and around it.

graphjs(bali)

Now, we can do a little more ere to make the visualisation cleaner and more useful. Like working in igraph, either we can set some attributes to the graph directly (like colors etc.) or we can state the options for the alterations when using the graphjs function. To demonstrate this, we will do a little of both.

First, let’s leave the network visualisation pretty basic and just play with some of the parameters of graphjs. In this, we are going to change the sizes of the nodes, add a title, and set the labels to show the names of the nodes. In this, as you hover over each node the role of the node appears at the top.

graphjs(bali,   
  vertex.size = 0.5,
  vertex.label = V(bali)$role,
  bg = "black",
  main = "Bali Terrorist Network"
)

This is much cleaner than the original visualisation. The contrast between the black backgorund and the orange nodes really makes the network pop and reducing the size of the nodes allows you to see the structure much clearer. There is a bit more we can do, however.

Let’s set a colour for each role that the individual plays in this network. To do this, we are adding a vertex attribute called role_colour using a case_when function from dplyr. The logic is pretty straightforward. Take a look.

V(bali)$role_colour <- case_when(
  V(bali)$role == "CT" ~ "gold",
  V(bali)$role == "OA" ~ "green",
  V(bali)$role == "BM" ~ "cyan",
  V(bali)$role == "SB" ~ "purple",
  V(bali)$role == "TL" ~ "orange"
)

graphjs(bali,   
  vertex.size = 0.5,
  vertex.label = V(bali)$role,
  vertex.color = V(bali)$role_colour,
  edge.color = "white",
  bg = "black",
  main = "Bali Terrorist Network"
)

Finally, for a little bit of fun, let’s apply some community detection to this network and change the colour of the nodes to reflect their community memberhsip. To do this, we can run a louvain community detection algorithm and adding the membership as an attribute to the network as a node characteristic we are calling group.

V(bali)$group <- cluster_louvain(bali)$membership 

graphjs(bali,   
  vertex.size = 0.5,
  vertex.label = V(bali)$role,
  vertex.color = V(bali)$group,
  bg = "white",
  main = "Bali Terrorist Network"
)

These 3D networks are really fun and a great way to engage viewers with the network. Next, we cover interactive visualisations that are slightly different from the above 3D networks. There are perks to both methods that become apparent as you use them.

B.3 Interactive Visualisation with VisNetwork

VisNetwork does not convert your network object into an interactive visualisation. Rather, we need to build a specific dataset that VisNetwork can pull the edge and node attributes from. To do this, we use the original network object to construct a node characteristics data frame.

nodes <- data.frame(
  id = V(bali)$vertex.names,
  label = V(bali)$role
)

edges <- igraph::as_data_frame(bali, what = "edges") %>%
  mutate(
    from = V(bali)$vertex.names[from],
    to = V(bali)$vertex.names[to]
  ) %>%
  select(from, to)

With this, we can construct our basic interactive network. The basic recipe for this is to use the visNetwork() function and call on the edgelist and node attribute dataset. With this visualisaiton, you can click on and drag nodes selecting them one-by-one. You will notice that the nodes are “springy.” This is a core feature of the package where it introduces some physics to the network to keep nodes that are tied together close together. We can play around with that in just a moment.

visNetwork(
    nodes,
    edges)

There is a lot more that we can do with this visualisation, however. The chunk below creates a much neater visualisation that we can use. It looks like a lot, but this is really just a sequence of small tweaks layered onto a base plot. In short, this process goes from initialising the network, defining the layout, defining groups, improve readability, adding interactivity, to adding legend. Let’s break it down by each option we add so you can get a picture of what it all does.

We start with visNetwork, where visNetwork(nodes_done, d_done, width = “100%”, height = “800px”, background = “white”) initializes the network and sets the canvas size and background. Next, visIgraphLayout(layout = “layout_nicely”) uses igraph to space nodes in a clean, readable way.

Next, visNodes(font = list(size = 30)) simply increases label size to improve readability. visOptions(highlightNearest = TRUE, nodesIdSelection = FALSE) adds light interactivity by highlighting connections on click while removing the dropdown selector. visPhysics(enabled = FALSE) freezes the layout so nodes don’t keep moving. You can drag and move the nodes around to place them where you want.

visNetwork(
    nodes,
    edges,
    width = "100%",
    height = "800px",
    background = "white") %>%
  visIgraphLayout(layout = "layout_nicely") %>%
  visNodes(
    font = list(size = 30)) %>%
  visOptions(
    highlightNearest = TRUE,
    nodesIdSelection = FALSE) %>%
  visPhysics(
    enabled = FALSE)

Now we have that base, we are going to add a few extra cool things to it! We can add back some physics to the visualisation, This introduces some repulsion back to the nodes reintroducing that ‘springy’ effect to the graph as you move the nodes. Rather than being able to place nodes where you want, this new network causes nodes to bound back into place after you drag it. However, you will notice that the additional options we introduce make for a little less strong ‘spring’ than the stock options.

visNetwork(
    nodes,
    edges,
    width = "100%",
    height = "800px",
    background = "white") %>%
  visNodes(
    font = list(size = 30)) %>%
  visOptions(
    highlightNearest = TRUE,
    nodesIdSelection = TRUE) %>%
  visPhysics(
    solver = "repulsion",
    repulsion = list(
      nodeDistance = 100,  
      centralGravity = 0.1,
      springLength = 200,
      springConstant = 0.02,
      damping = 0.09
    ),
    stabilization = list(enabled = TRUE, iterations = 100)
  )

Here is a slightly different alteration of the physics with a slightly different layout, and we can add some control buttons directly to the visualisation so that users can navigate the visualisation by clicking not dragging their mouse. Finally, to mimic the community detection visualusation that we did above, we add an grouping attribute to the vertex dataset that pulls the clustering membership from the same louvain method we used in our 3D network. The result, shows a colour for each of the identified clusters in the network.

# creating the clustering memberhship
nodes$group <- as.factor(cluster_louvain(bali)$membership)

visNetwork(
  nodes,
  edges,
  width = "100%",
  height = "800px",
  background = "white"
) %>%
  visInteraction(
    navigationButtons = TRUE
  ) %>%
  visNodes(
    font = list(size = 30)
  ) %>%
  visOptions(
    highlightNearest = TRUE,
    nodesIdSelection = TRUE
  ) %>%
  visPhysics(
    solver = "forceAtlas2Based",
    forceAtlas2Based = list(
      gravitationalConstant = -50,
      centralGravity = 0.01,
      springLength = 200,
      springConstant = 0.05,
      damping = 0.4
    ),
    stabilization = list(enabled = TRUE)
  )

B.4 Saving Advanced Network Visualisations

Since these types of visualisations are not static, we can’t simply save them to a jpeg or png file. Instead, they need to be stored in a file that will open and permit the interactivity. As such, we save them to an .html file that you can open in your broswer.

Here we use a combination of functions from a couple of html-friendly packages. Note that this process applies for both packages. Basically, what this does is ensure that the visualisation can be opened in a browser, then saves it to your working directory as a html file and opens it in your default browser.

# Store it
bali_3d <- graphjs(bali,   
  vertex.size = 0.5,
  vertex.label = V(bali)$role,
  vertex.color = V(bali)$group,
  bg = "white",
  main = "Bali Terrorist Network"
)

# Make is browsable
bali_3d <- browsable(bali_3d)

# Save it
saveWidget(bali_3d, file="bali_3d.html")

# Open it
browseURL("bali_3d.html")

B.5 References

For more information about the dataset we used in this chapter…

  • Koschade, S. (2006). A social network analysis of Jemaah Islamiyah: The applications to counter-terrorism and intelligence. Studies in Conflict and Terrorism, 29, 559–575.

  • Magouirk, J., Atran, S., & Sageman, M. (2008). Connecting Terrorist Networks. Studies in Conflict & Terrorism, 31(1), 1–16. https://doi.org/10.1080/10576100701759988

For more on Interactive and 3D Networks…