import networkx as nx
import igviz as ig
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).
To install run pip install igviz
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.
= nx.random_geometric_graph(200, 0.125)
G 12, "prop")
nx.set_node_attributes(G, 3, "edge_prop") nx.set_edge_attributes(G,
Now we plot!
The Basics
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!
= ig.plot(G)
fig 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)
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.
= ig.plot(
fig # Your graph
G, ="My Graph",
title="static", # Makes node sizes the same
size_method="#ffcccb", # Makes all the node colours black,
color_method=["prop"], # Adds the 'prop' property to the hover text of the node
node_text="Visualization made by <a href='https://github.com/Ashton-Sidhu/plotly-graph'>igviz</a> & plotly.", # Adds a text annotation to the graph
annotation_text
)
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.
= ig.plot(
fig
G,="My Graph",
title="prop", # Makes node sizes the size of the "prop" property
size_method="prop", # Colors the nodes based off the "prop" property and a color scale,
color_method=["prop"], # Adds the 'prop' property to the hover text of the node
node_text
)
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.
= []
color_list = []
sizing_list
for node in G.nodes():
= G.degree(node) * 3
size_and_color
color_list.append(size_and_color)
sizing_list.append(size_and_color)
= ig.plot(
fig
G,="My Graph",
title=sizing_list, # Makes node sizes the size of the "prop" property
size_method=color_list, # Colors the nodes based off the "prop" property and a color scale,
color_method=["prop"], # Adds the 'prop' property to the hover text of the node
node_text
)
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,="prop", # Display the "prop" attribute as a label on the node
node_label="top center", # Display the node label directly above the node
node_label_position=["edge_prop"], # Display the "edge_prop" attribute on hover over the edge
edge_text="edge_prop", # Display the "edge_prop" attribute on the edge
edge_label="bottom center", # Display the edge label below the edge
edge_label_position )
/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.
= ig.plot(
fig
G,="My Graph",
title="kamada"
layout
)
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
...
}
"pos")
nx.set_node_attributes(G, pos_dict,
= ig.plot(G)
fig
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.