Frage

I've been studying the other networkx plotting posts, but I've been having a hard time adapting them to my problem.

1) How do I create subplots with network graphs, without a PREDEFINED number of objects to plot? The function grabs this dynamically.

2) Is there an easy way to filter the network graph by limiting only those edges with over a weight of 2, for instance? or do I have to edit the network object itself to do so?

UPDATE #2: I figured out a way to filter by degree (see below). I'm wondering more generally if there are better ways to make my network data more understandable?

nol comes in the format [ [Year, networkobject], [Year, networkobject]]

def standardgraph_multiyear(nol, minimumdegree):
"""
Plots multiple graphs based on year
nol = takes in a LIST of [year, network object]
minimum = takes in a digit to filter nodes by degree
"""

#Each iteration prints a new subplot 
numrows = len(nol)
fig = plt.figure(figsize=(10,60))    
for i, val in enumerate(nol):
    gloc = numrows,1,i+1
    plt.subplot(numrows, 1, i+1)

    if minimumdegree > 0:
        outdeg = val[1].degree()
        to_keep = [n for n in outdeg if outdeg[n] > minimumdegree]
        mingraph = val[1].subgraph(to_keep)
        pos = nx.spring_layout(mingraph, iterations=200)
        nx.draw(mingraph, pos, font_size=8, with_labels=True)
        nx.draw_networkx_edges(mingraph, pos, alpha=.2)
        nx.draw_networkx_nodes(mingraph, pos, node_size=60, font_size =8, labels=True)
        nx.draw_networkx_labels(mingraph, pos, font_color='k', font_size=8)
        plt.title("Year {0}".format(val[0]), loc = 'center', fontsize=20)

    if minimumdegree == 0:
        outdeg = val[1].degree()
        to_keep = [n for n in outdeg if outdeg[n] > minimumdegree]
        mingraph = val[1].subgraph(to_keep)
        pos = nx.spring_layout(mingraph, iterations=200)
        nx.draw(mingraph, pos, font_size=8, with_labels=True)
        nx.draw_networkx_edges(mingraph, pos, alpha=.2)
        nx.draw_networkx_nodes(mingraph, pos, node_size=60, font_size =8, labels=True)
        nx.draw_networkx_labels(mingraph, pos, font_color='k', font_size=8)
        plt.title("Year {0}".format(val[0]), loc = 'center', fontsize=20)
return 

fig.savefig('out.png', dpi=100)

War es hilfreich?

Lösung

Your out of range error likely comes from the call to plt.subplot(221+i), since you don't seem to limit i to be <4; thus matplotlib will not know what subplot you intend to refer to?

(You also seem to have some conflicting code assembling the plots: a call to plt.subplots(1,1) and a later which requests a 2x2 grid).

In a different question I used the more basic plt.subplot(xxx) syntax to generate multiple subplots (following the four grids example from networkx). But you can also do it as shown below, setting the ax= keyword argument to an already existing set of axes. Note the call to sca() before rendering to each axis, which I needed to get this to work.

I've also shown one way to filter the edges that are shown below, and it does not require modifying the underlying graph: instead, you construct the edge lineweights you want based on the data from your graph, and use that as argument to draw_networkx_edges.

Edit (re updated question): the example code now includes a more explicit illustration of how to handle an unknown number of networks.

import matplotlib.pyplot as plt
import networkx as nx
import numpy as np

n = 15; m = 40                        # graph size
L = np.random.choice(xrange(n), 2*m)  # select some edge destinations
weights = 0.5 + 5 * np.random.rand(m) # give each edge a weight


G = nx.Graph()                           # create a graph object
G.add_nodes_from(xrange(n))              # add n nodes to it
for i, (fr, to) in enumerate(zip(L[1::2], L[::2])): 
  G.add_edge(fr, to, weight=weights[i])  # add each edge

# use one of the edge properties to control line thickness
edgewidth = [ d['weight'] for (u,v,d) in G.edges(data=True)]

# and create a filtered version (still need an entry for each edge)
w_threshold = 2
edgewidth_filtered = [ d['weight'] if d['weight'] > w_threshold else 0
                      for (u,v,d) in G.edges(data=True)]

# alt. filtering - all edges that meet some criterion are displayed uniformly 
binary_filtered_edges = [ 1 if d['weight'] > w_threshold else 0
                      for (u,v,d) in G.edges(data=True)]

titles = [ 'edges drawn with lineweight=1', 'edge width from edge weight',
  'edge width from edge weight, only strong edges',
  'strong edges shown as lineweight=1', ]

edge_display_params = [ np.ones(len(edgewidth),), edgewidth,  
  edgewidth_filtered, binary_filtered_edges,]

# to illustrate drawing an unknown number of graphs, add some repeats repeats
n_extra = np.random.randint(0, 5)
indices = range(len(edge_display_params)) * 3
indices = indices[len(edge_display_params) + n_extra:]

# layout
pos = nx.spring_layout(G, iterations=50)
pos = nx.circular_layout(G)
#pos = nx.random_layout(G)

# rendering
fig = plt.figure(1); plt.clf()
# compute a grid size that will fit all graphs on it (couple blanks likely)
nr = int(np.ceil(np.sqrt(len(indices))))
fig, ax = plt.subplots(nr, nr, num=1)

for i, j in enumerate(indices):
    # dereference index into valid data (needed here since some repeated rather
    # than creating more, to illustrate handling unknown amount of data)
    k = indices[j]
    widths = edge_display_params[k]
    # compute index for the subplot, and set this subplot as current
    ix = np.unravel_index(i, ax.shape)
    plt.sca(ax[ix])
    # draw all nodes homogeneously, and edge weights as filtered
    nx.draw_networkx_nodes(G, pos, ax=ax[ix])
    nx.draw_networkx_edges(G, pos, width=widths, ax=ax[ix],)

    ax[ix].set_title(titles[k], fontsize=10)
    ax[ix].set_axis_off()

plt.show()

edge line thickness based on data

This example uses the same input graph four times over but obviously you could apply a single filter to different graphs (by filtering within the plotting loop) instead of applying different filters.


Below shows one run that created an extra 4 graphs, and so we have one unused pane:

unknown number of graphs

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top