
A network graph is a form of visualization that enables you to visualize and analyze the relationships between entities. For example, the following figure shows the contribution of Wikipedia editors to the various Wikipedia language versions during one month in the summer of 2013.

From the network graph, you can gather a few observations:
- English (en) is the dominant language where all the other languages are translated into; at the same time, a lot of English materials are also translated into other languages
- Chinese (zh) is translated into Japanese (ja), but not the other way
- Both Chinese and Japanese materials are translated into English, and vice versa
In this article, I will show you the basics of plotting network graphs using the NetworkX package.
Installing NetworkX
To install the NetworkX package, use the pip
command:
!pip install networkx
Some Graph Terminologies
Before you start plotting your network graph, it is useful to understand some basic network graph terminologies.
The following figure shows a Directed Graph (also known as a digraph; a graph in which the edges have a direction as indicated by the arrows):

- The nodes are the fundamental units in a graph. Nodes are also commonly known as vertices.
- The edges are the connections between two nodes in the graph.
An undirected graph, on the other hand, has no directions between nodes (and hence no arrows) and the edges are bidrectional.
Creating a Graph
Let’s now get to work to create a Network Graph. We shall do this step-by-step.
First, create a networkx.classes.graph.Graph
object:
import Networkx as nx
G = nx.Graph()
print(G)
# Graph with 0 nodes and 0 edges
The nx.Graph()
class creates a Undirected Graph. If you want to create a directed graph, use nx.DiGraph(directed=True)
, which returns an networkx.classes.digraph.DiGraph
object.
We will talk about directed graph later in this article.
Adding Nodes
With the graph created (G
), you now need to add some nodes to it:
G.add_node("Singapore")
G.add_node("San Francisco")
G.add_node("Tokyo")
print(G)
# Graph with 3 nodes and 0 edges
The above code snippet added three nodes to the graph, with no edges defined (yet). Besides using the add_node()
function to add individual nodes, you can also add multiple nodes in one go using the add_nodes_from()
function:
G.add_nodes_from(["Riga", "Copenhagen"])
print(G)
# Graph with 5 nodes and 0 edges
Your graph has five nodes at this moment.
Adding Edges
With the nodes defined, you can now add the edges to connect them:
G.add_edge("Singapore","San Francisco")
G.add_edge("San Francisco","Tokyo")
G.add_edges_from(
[
("Riga","Copenhagen"),
("Copenhagen","Singapore"),
("Singapore","Tokyo"),
("Riga","San Francisco"),
("San Francisco","Singapore"),
]
)
print(G)
# Graph with 5 nodes and 6 edges
Like nodes, you can add individual edge using the add_edge()
function, or add multiple edges using the add_edges_from()
function (just supply a list of tuples representing each edge).
Drawing the Graph
With the nodes and edges added to the graph, you are now ready to visualize the graph using the draw()
function:
nx.draw(G)
You should see something like this:

Note that you will get a different graph every time you call the
draw()
function.
Here is another variation of the same graph:

Displaying the labels
Apparently, a graph without labels is not very useful (if useable at all!). So let’s draw the graph with the nodes labelled:
nx.draw(G, with_labels = True)
The above
draw()
function with thewith_labels
parameter is equivalent to calling the following functions:
nx.draw_networkx_nodes()
– draws all the nodes in the graphnx.draw_networkx_labels()
– draws the labels on each nodenx.draw_networkx_edges()
– draws the edges connecting the nodes
So what are the advantages of using the
draw()
function vs the other functions? Well, drawing using the individual functions allow you to customize the look and feel of individual nodes, labels, and edges.
You can now see the label for each node:

Using layouts
Remember that the draw()
function uses a different layout for your graph every time you plot it? Well, you can specify the layout you want to use for your graph. Here is an example:
pos = nx.circular_layout(G)
nx.draw(G, pos, with_labels = True)
All the nodes will now be arranged in a circular manner:

Alternatively, you can also draw the graph using the circular layout through the nx.draw_circular()
function (instead of the nx.draw()
function):
nx.draw_circular(G, with_labels = True)
You can try the other layouts:
nx.draw_kamada_kawai(G, with_labels = True)
nx.draw_planar(G, with_labels = True)
nx.draw_random(G, with_labels = True)
nx.draw_spectral(G, with_labels = True)
nx.draw_spring(G, with_labels = True)
nx.draw_shell(G, with_labels = True)
Labelling the edges
With the nodes labelled, you might also want to label the edges. You can do so via the nx.draw_networkx_edge_labels()
function.
pos = nx.circular_layout(G)
nx.draw(G, pos, with_labels = True)
nx.draw_networkx_edge_labels(
G,
pos,
edge_labels={
("Singapore","Tokyo"): '2 flights daily',
("San Francisco","Singapore"): '5 flights daily',
},
font_color='red'
)
The above code snippets labels the two edges for the three nodes:

Directed Graph
So far our graph is undirected. In some cases it might be useful to plot a directed graph. For instance, in our example the edges might represent the flights between two cities. Using a directed graph allows us to visually inspect which are the flights going from one city to another. The following code snippet shows our example now plotted as a directed graph:
import networkx as nx
#---directed graph---
G = nx.DiGraph(directed=True)
# add nodes
G.add_node("Singapore")
G.add_node("San Francisco")
G.add_node("Tokyo")
G.add_nodes_from(["Riga", "Copenhagen"])
# add edges
G.add_edge("Singapore","San Francisco")
G.add_edge("San Francisco","Tokyo")
G.add_edges_from(
[
("Riga","Copenhagen"),
("Copenhagen","Singapore"),
("Singapore","Tokyo"),
("Riga","San Francisco"),
("San Francisco","Singapore"),
]
)
# set layout
pos = nx.circular_layout(G)
# draw graph
nx.draw(G, pos, with_labels = True)
# draw edge labels
nx.draw_networkx_edge_labels(
G, pos,
edge_labels={
("Singapore","Tokyo"): '2 flights daily',
("San Francisco","Singapore"): '5 flights daily',
},
font_color='red'
)
You can now observe that there are flights from Singapore to San Francisco, and vice versa. On the other hand, there is flights from Riga to San Francisco, but not the other way round.

Customizing the Nodes
By default, the nodes are blue in color and the size is pretty small. You can customize the nodes as well as the edge color by passing a dictionary to the draw()
function:
options = {
'node_color': 'yellow', # color of node
'node_size': 3500, # size of node
'width': 1, # line width of edges
'arrowstyle': '-|>', # array style for directed graph
'arrowsize': 18, # size of arrow
'edge_color':'blue', # edge color
}
nx.draw(G, pos, with_labels = True, arrows=True, **options)
The nodes are now in yellow (and bigger) and the edges are in blue:

Outlining the Nodes
If you want to outline the nodes, you need to manually do it using matplotlib
. The following code snippet sets the figure size to 10 inches by 10 inches (width x height) and then use the set_edgecolor()
function to draw a black outline for each node:
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 10))
pos = nx.circular_layout(G)
options = {
'node_color': 'yellow',
'node_size': 8500,
'width': 1,
'arrowstyle': '-|>',
'arrowsize': 18,
}
nx.draw(G, pos, with_labels = True, arrows=True, **options)
ax = plt.gca()
ax.collections[0].set_edgecolor("#000000")
Each of the nodes now have a black outline:

If you did not set the figure size, your graph may look like this:

Setting Node Colors
To give each node a different color, you can specify a color palette, such as from bokeh
, and set the color in the node_color
key in the dictionary to be passed into the draw()
function:
from networkx import *
import matplotlib.pyplot as plt
from bokeh.palettes import Spectral
plt.figure(figsize=(8, 8))
pos = nx.circular_layout(G)
options = {
'node_color': Spectral[5], # first 5 colors from the Spectral palette
'node_size': 8500,
'width': 1,
'arrowstyle': '-|>',
'arrowsize': 18,
}
nx.draw(G, pos=pos, with_labels = True, arrows=True, **options)
ax = plt.gca()
ax.collections[0].set_edgecolor("#000000")
The graph will now have different colors for each node:

If you want to specify your own colors, you can set them manually in the dictionary:
options = {
'node_color': ['yellow','magenta','lightblue','lightgreen','pink'],
'node_size': 8500,
'width': 1,
'arrowstyle': '-|>',
'arrowsize': 18,
}
Related Articles
Building Interactive Network Graphs using pyvis
Visualizing Geospatial Network Graphs using Basemap and mplleaflet
If you like reading my articles and that it helped your career/study, please consider signing up as a Medium member. It is $5 a month, and it gives you unlimited access to all the articles (including mine) on Medium. If you sign up using the following link, I will earn a small commission (at no additional cost to you). Your support means that I will be able to devote more time on writing articles like this.
Summary
In this article, I discussed the basics of network graph and how it is useful to let you visualize the relationships between different entities in your dataset. For this article, my focus is on how to use the NetworkX package to plot the graph. In my next article, I will make use of the Flights Delay dataset and visualize the connections between different airports. Stay tuned!