Creating Network Graphs with Python


Contents

Overview

NetworkX can be used to plot network graphs with python code. You'll need to install this package in your own local development environment. At this stage is not possible to run NetworkX code on Udacity's IDE. For 3D plotting refer to the Mayavi sections.

networkx-graph-movies-1.png

How to Install NetworkX

Ready-made Distributions

These python distributions already include NetworkX:

General Instructions

You'll need to install setuptools, numpy and matplotlib, if you don't have them. Then download networkx's *.egg file from here and install it by calling easy_install from the command-line shell, e.g.:

$ easy_install networkx-1.7rc1-py2.7.egg

Linux Ubuntu and Debian

From the terminal run the following command:

$ sudo apt-get install python-networkx

Windows

Python 2.7 is highly recommended due to other versions not being supported by one or more of NetworkX's dependencies. Specific instructions for a few popular Python distributions follow:

Active State

From the Windows command prompt (cmd) run the following command:

C:\> pypm install networkx

Python Software Foundation

Install the following dependencies first:

  • Install setuptools by following these instructions.
  • Download numpy from here and run the installer.
  • Download matplotlib from here and run the installer.

Finally download networkx's *.egg file from here and install it by calling easy_install from the command prompt, e.g.:

C:\> cd C:\folder\where\your\egg\file\is\located

C:\folder\where\your\egg\file\is\located> easy_install networkx-1.7rc1-py2.7.egg

NetworkX Example Code

Additional examples can be found here. A couple of examples follow bellow.

A very, very simple plot:

import networkx as nx
import matplotlib.pyplot as plt

def draw_graph(graph):

    # extract nodes from graph
    nodes = set([n1 for n1, n2 in graph] + [n2 for n1, n2 in graph])

    # create networkx graph
    G=nx.Graph()

    # add nodes
    for node in nodes:
        G.add_node(node)

    # add edges
    for edge in graph:
        G.add_edge(edge[0], edge[1])

    # draw graph
    pos = nx.shell_layout(G)
    nx.draw(G, pos)

    # show graph
    plt.show()

# draw example
graph = [(20, 21),(21, 22),(22, 23), (23, 24),(24, 25), (25, 20)]
draw_graph(graph)

networkx-graph-example-simple-1.png

A more sophisticated example, where you can change some of your graph's properties (colors, node size, edge tickness, etc):

import networkx as nx
import matplotlib.pyplot as plt

def draw_graph(graph, labels=None, graph_layout='shell',
               node_size=1600, node_color='blue', node_alpha=0.3,
               node_text_size=12,
               edge_color='blue', edge_alpha=0.3, edge_tickness=1,
               edge_text_pos=0.3,
               text_font='sans-serif'):

    # create networkx graph
    G=nx.Graph()

    # add edges
    for edge in graph:
        G.add_edge(edge[0], edge[1])

    # these are different layouts for the network you may try
    # shell seems to work best
    if graph_layout == 'spring':
        graph_pos=nx.spring_layout(G)
    elif graph_layout == 'spectral':
        graph_pos=nx.spectral_layout(G)
    elif graph_layout == 'random':
        graph_pos=nx.random_layout(G)
    else:
        graph_pos=nx.shell_layout(G)

    # draw graph
    nx.draw_networkx_nodes(G,graph_pos,node_size=node_size, 
                           alpha=node_alpha, node_color=node_color)
    nx.draw_networkx_edges(G,graph_pos,width=edge_tickness,
                           alpha=edge_alpha,edge_color=edge_color)
    nx.draw_networkx_labels(G, graph_pos,font_size=node_text_size,
                            font_family=text_font)

    if labels is None:
        labels = range(len(graph))

    edge_labels = dict(zip(graph, labels))
    nx.draw_networkx_edge_labels(G, graph_pos, edge_labels=edge_labels, 
                                 label_pos=edge_text_pos)

    # show graph
    plt.show()

graph = [(0, 1), (1, 5), (1, 7), (4, 5), (4, 8), (1, 6), (3, 7), (5, 9),
         (2, 4), (0, 4), (2, 5), (3, 6), (8, 9)]

# you may name your edge labels
labels = map(chr, range(65, 65+len(graph)))
#draw_graph(graph, labels)

# if edge labels is not specified, numeric labels (0, 1, 2...) will be used
draw_graph(graph)

networkx-graph-example-pretty-1.png

3D Graphs with Mayavi

You may wish to install Mayavi as well and extend the capabilities of NetworkX to plot interactive 3D graphs:

mayavi-graph-example-random-1.png

How to Install Mayavi

Ready-made Distributions

These Python distributions already include Mayavi:

General Instructions

Install instructions for all platforms can be found here.

Linux Ubuntu and Debian

First be sure that you have all of Mayavi's dependencies installed by executing the following command from the terminal:

sudo apt-get install python-wxgtk2.8 python-wxtools wx2.8-i18n python-vtk python-setuptools python-numpy python-configobj python-networkx

Finally install Mayavi by executing the following command:

sudo easy_install "Mayavi[app]"

Windows

In case you don't already have these packages:

  • Install setuptools by following these instructions.
  • Download numpy from here and run the installer.
  • Download matplotlib from here and run the installer.
  • Download VTK from here and run the installer.
  • Download wxPyton from here and run the installer.

Finally install Mayavi by executing the following commands from the Windows command-prompt (cmd):

C:> easy_install Sphinx EnvisageCore EnvisagePlugins configobj

C:> easy_install Mayavi[app]

Mayavi Example Code

The following example plots a tangled hypercube:

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from mayavi import mlab

import random

def draw_graph3d(graph, graph_colormap='winter', bgcolor = (1, 1, 1),
                 node_size=0.03,
                 edge_color=(0.8, 0.8, 0.8), edge_size=0.002,
                 text_size=0.008, text_color=(0, 0, 0)):

    H=nx.Graph()

    # add edges
    for node, edges in graph.items():
        for edge, val in edges.items():
            if val == 1:
                H.add_edge(node, edge)

    G=nx.convert_node_labels_to_integers(H)

    graph_pos=nx.spring_layout(G, dim=3)

    # numpy array of x,y,z positions in sorted node order
    xyz=np.array([graph_pos[v] for v in sorted(G)])

    # scalar colors
    scalars=np.array(G.nodes())+5
    mlab.figure(1, bgcolor=bgcolor)
    mlab.clf()

    pts = mlab.points3d(xyz[:,0], xyz[:,1], xyz[:,2],
                        scalars,
                        scale_factor=node_size,
                        scale_mode='none',
                        colormap=graph_colormap,
                        resolution=20)

    for i, (x, y, z) in enumerate(xyz):
        label = mlab.text(x, y, str(i), z=z,
                          width=text_size, name=str(i), color=text_color)
        label.property.shadow = True

    pts.mlab_source.dataset.lines = np.array(G.edges())
    tube = mlab.pipeline.tube(pts, tube_radius=edge_size)
    mlab.pipeline.surface(tube, color=edge_color)

    mlab.show() # interactive window

# create tangled hypercube
def make_graph(nodes):

    def make_link(graph, i1, i2):
        graph[i1][i2] = 1
        graph[i2][i1] = 1

    n = len(nodes)

    if n == 1: return {nodes[0]:{}}

    nodes1 = nodes[0:n/2]
    nodes2 = nodes[n/2:]
    G1 = make_graph(nodes1)
    G2 = make_graph(nodes2)

    # merge G1 and G2 into a single graph
    G = dict(G1.items() + G2.items())

    # link G1 and G2
    random.shuffle(nodes1)
    random.shuffle(nodes2)
    for i in range(len(nodes1)):
        make_link(G, nodes1[i], nodes2[i])

    return G

# graph example
nodes = range(16)
graph = make_graph(nodes)
draw_graph3d(graph)

mayavi-graph-example-tangled-hypercube-1.png