Machine learning engineer based in London, UK.
2017-02-13 01:14:00 +0000
There was going to be a series of posts about how to make pretty(-ish) graphs using NetworkX in Python and VisNetwork in R. I started working on a few back in July. However, I don’t really have time to condense all the various notes I made while working at NIBR. So instead, a few bits of miscellany follow and may be added to in the future.
VisNetwork is fantastic. You can hook it up to Shiny to make pretty, interactive web apps that allow people to explore data in visual graph format. Everything you need to know is in the best tutorial for using VisNetwork in R.
So there seem to be a few possibilities: pygraphviz, pydot among them. I went for NetworkX because it had the most documentation.
Code for colouring subsets of edges and nodes in NetworkX in Python (2.7). In this case I use M and G to denote subsets of nodes (since I was combining metabolomic and genomic datasets), and have three different groups of edges.
import numpy as np
import matplotlib.pyplot as plt
import networkx as nx
import pickle as pk
def make_gm_dict():
MMid = pk.load(open('data/MMid.txt')).values
MGid = pk.load(open('data/MGid.txt')).values
gm_dict = dict()
for m in MMid:
gm_dict[m] = 'M'
for g in MGid:
gm_dict[g] = 'G'
return gm_dict
def identify_gm_nodes(gm_dict, g):
node_names = g.nodes()
g_nodes = []
m_nodes = []
for n in node_names:
n = str(n)
if gm_dict[n] != "M":
g_nodes.append(n)
else:
m_nodes.append(n)
return g_nodes, m_nodes
def draw_nodes(G, pos, nodelist, node_color):
nx.draw_networkx_nodes(G, pos, node_size = 300,
nodelist = nodelist, node_color = node_color, alpha = 0.9)
return None
def draw_edge_layer(G, pos, edge_alpha, edge_color, edge_list, weight_list, width_scaler = 1):
width_list = [width_scaler * w for w in weight_list]
nx.draw_networkx_edges(G, pos, edgelist = edge_list,
edge_color = edge_color,
alpha = edge_alpha,
arrows = False,
width = width_list)
return None
def get_edges_from_file(root_node):
fname = 'data/edges/edges_shallow_%s.txt'% (''.join(
e for e in root_node if e.isalnum()))
f = open(fname, 'r')
edges = pk.load(f)
f.close()
return edges
def plot_network(edges, root_node):
## Prepare the graph
w_edge_list = list(edges[['src', 'dest', 'wt']].itertuples(index = False))
G = nx.MultiDiGraph()
G.add_weighted_edges_from(w_edge_list)
# Create positions of nodes using a spring layout
# Use a high spring strength to keep the graph small
pos = nx.layout.fruchterman_reingold_layout(G, k = (2/np.sqrt(len(G.nodes()))))
g_nodes, m_nodes = identify_gm_nodes(gm_dict, G)
## Draw nodes
draw_nodes(G, pos, m_nodes, 'r')
draw_nodes(G, pos, g_nodes, 'b')
highlight_nodes = []
highlight_nodes.append(root_node)
draw_nodes(G, pos, highlight_nodes, 'm')
#draw_edge_layer(G, pos, 0.3, 'k', *layer_edge_list(edges, 3))
draw_edge_layer(G, pos, 0.5, 'y', *layer_edge_list(edges, 2))
draw_edge_layer(G, pos, 0.7, 'c', *layer_edge_list(edges, 1))
draw_edge_layer(G, pos, 0.9, 'm', *layer_edge_list(edges, 0))
nx.draw_networkx_labels(G, pos, font_size = 10, font_weight = 'bold', font_color = '0.95')
ax = plt.gca()
ax.set_axis_bgcolor('0.5') # Grey background (0 is darker)
ax.grid(b = False) # No gridlines
ax.get_xaxis().set_visible(False) # hide x-axis (to avoid confusing labels)
ax.get_yaxis().set_visible(False) # hide y-axis
return None