Intro to Interactive Graph Visualizations

Build interactive graph network visualizations.
jupyter
graph
visualization
Author

Ashton Sidhu

Published

March 27, 2020

Over the last couple of months I have started to explore more with Graphs and network analysis as it pertains to user behaviour in cyber security. One of the main pain points I found early on was visualizing the network, the node properties and edges in a neat, visually appealing way. Alot of the default plotting options are built on Matplotlib, which is well, let’s just say suboptimal for this type of visualization.

Instead of playing around with the Matplotlib axes api, I wanted something a little bit more robust, easier to use out of the box, visually appealing and neat while maximizing the possible amount of information that can be displayed on the graph.

In comes my favourite visualization library Plotly. Plotly already had some documentation on how to visualize graphs, but it was still a fairly lengthy process. The goal was to find (or create) a uniform api that follows the .plot standard, with some customizability, but for graphs. Hence, why I made this little package called Interactive Graph Visualizations (igviz).

Note

Currently, only Networkx is supported but the next step is expanding it to Apache’s Graphx.

To install run pip install igviz

import networkx as nx
import igviz as ig

Create a random graph for demonstration purposes and assign every node a property called prop and every edge a property called “edge_prop” and make the values 12 and 3.

G = nx.random_geometric_graph(200, 0.125)
nx.set_node_attributes(G, 12, "prop")
nx.set_edge_attributes(G, 3, "edge_prop")

Now we plot!

Note

This also works with Directed and Multigraphs. Directed Graphs will show the arrows from node to node.

The Basics

Tip

All the example notebooks can be found here.

By default, the nodes are sized and coloured by the degree of itself. The degree of a node is just the number of edge’s (lines connecting 2 nodes) it has. You can see the degree of the node by hovering over it!

fig = ig.plot(G)
fig.show()
/tmp/ipykernel_19017/633761989.py:1: DeprecationWarning: Argument `titlefont_size` is deprecated and will be removed in 0.6.0.
  fig = ig.plot(G)
Tip

When it comes to customizability, you can change the how the nodes are sized (size_method) to either be static, based off a node’s property or your own custom sizing method.

Tip

The color’s can be changed (color_method) to be a static color (hex, plain text, etc.), based off a node’s property or your own custom color method.

There are more options, and more to come, but those are the ones that greatly impact the visualization and information of your graph.

Customizing the Graph Appearance

Here all the nodes are set to the same size and the colour is set to a light red while displaying the prop property on hover.

Tip

To display Node’s properties when you hover it, specify a list for the node_text parameter of node properties you want to have displayed. By default only degree is shown.

fig = ig.plot(
    G, # Your graph
    title="My Graph",
    size_method="static", # Makes node sizes the same
    color_method="#ffcccb", # Makes all the node colours black,
    node_text=["prop"], # Adds the 'prop' property to the hover text of the node
    annotation_text="Visualization made by <a href='https://github.com/Ashton-Sidhu/plotly-graph'>igviz</a> & plotly.", # Adds a text annotation to the graph
)

fig.show()
/tmp/ipykernel_19017/885303569.py:1: DeprecationWarning:

Argument `titlefont_size` is deprecated and will be removed in 0.6.0.

Here, the sizing and color method is based off the prop property of every node as well as we’re displaying the prop property on hover.

fig = ig.plot(
    G,
    title="My Graph",
    size_method="prop", # Makes node sizes the size of the "prop" property
    color_method="prop", # Colors the nodes based off the "prop" property and a color scale,
    node_text=["prop"], # Adds the 'prop' property to the hover text of the node
)

fig.show()
/tmp/ipykernel_19017/554760700.py:1: DeprecationWarning:

Argument `titlefont_size` is deprecated and will be removed in 0.6.0.

To add your own sizing and color methods, pass in a list of a color or size pertaining to each node in the graph to the size_method and color_method parameters.

Tip

To change the colorscale, change the colorscale parameter!

color_list = []
sizing_list = []

for node in G.nodes():
    size_and_color = G.degree(node) * 3

    color_list.append(size_and_color)
    sizing_list.append(size_and_color)

fig = ig.plot(
    G,
    title="My Graph",
    size_method=sizing_list, # Makes node sizes the size of the "prop" property
    color_method=color_list, # Colors the nodes based off the "prop" property and a color scale,
    node_text=["prop"], # Adds the 'prop' property to the hover text of the node
)

fig.show()
/tmp/ipykernel_19017/1171289552.py:10: DeprecationWarning:

Argument `titlefont_size` is deprecated and will be removed in 0.6.0.

Labels

You can also add labels to both nodes and edges as well as add hover text to the edges based on their attributes.

ig.plot(
    G,
    node_label="prop", # Display the "prop" attribute as a label on the node
    node_label_position="top center", # Display the node label directly above the node
    edge_text=["edge_prop"], # Display the "edge_prop" attribute on hover over the edge
    edge_label="edge_prop", # Display the "edge_prop" attribute on the edge
    edge_label_position="bottom center", # Display the edge label below the edge
)
/tmp/ipykernel_19017/1570631554.py:1: DeprecationWarning:

Argument `titlefont_size` is deprecated and will be removed in 0.6.0.

Layouts

You can change the way your graph is oragnized and laid out by specifying a type of layout. Networkx comes with predefined layouts to use and we can apply them through layout.

By default, igviz looks for the pos node property and if it doesn’t exist it will default to a random layout.

The supported layouts are:

  • random (default): Position nodes uniformly at random in the unit square. For every node, a position is generated by choosing each of dim coordinates uniformly at random on the interval [0.0, 1.0).

  • circular: Position nodes on a circle.

  • kamada: Position nodes using Kamada-Kawai path-length cost-function.

  • planar: Position nodes without edge intersections, if possible (if the Graph is planar).

  • spring: Position nodes using Fruchterman-Reingold force-directed algorithm.

  • spectral: Position nodes using the eigenvectors of the graph Laplacian.

  • spiral: Position nodes in a spiral layout.

fig = ig.plot(
    G,
    title="My Graph",
    layout="kamada"
)

fig.show()
/tmp/ipykernel_19017/1973471548.py:1: DeprecationWarning:

Argument `titlefont_size` is deprecated and will be removed in 0.6.0.

To add your own pos property you can set it via the nx.set_node_attributes function.

pos_dict = {
    0: [1, 2], # X, Y coordinates for Node 0
    1: [1.5, 3], # X, Y coordinates for Node 1
    ...
}

nx.set_node_attributes(G, pos_dict, "pos")

fig = ig.plot(G)

fig.show()

Feedback

I encourage all feedback about this post or Igviz. You can e-mail me at sidhuashton@gmail.com or leave a comment on the post.

Any bug or feature requests, please create an issue on the Github repo. I welcome all feature requests and any contributions. This project is a great starter if you’re looking to contribute to an open source project — you can always message me if you need assistance getting started.

Tip

If you like the project, give it a star!