简体   繁体   中英

Is it possible to control the order that nodes are drawn using NetworkX in python?

I have a large graph object with many nodes that I am trying to graph. Due to the large number of nodes, many are being drawn one over another. This in itself is not a problem. However, a small percentage of nodes have node attributes which dictate their colour.

Ideally I would be able to draw the graph in such a way that nodes with this property are drawn last, on top of the other nodes, so that it is possible to see their distribution across the graph.

The code I have so far used to generate the graph is shown below:

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import os
import pickle
from pathlib import Path

def openFileAtPath(filePath):
    print('Opening file at: ' + filePath)
    with open(filePath, 'rb') as input:
        file = pickle.load(input)
        return file 

# Pre manipulation path
g = openFileAtPath('../initialGraphs/wordNetadj_dictionary1.11.pkl')

# Post manipulation path
# g = openFileAtPath('../manipulatedGraphs/wordNetadj_dictionary1.11.pkl')

print('Fetching SO scores')

scores = list()

for node in g.nodes:
    scores.append(g.node[node]['weight'])

print('Drawing network')

nx.draw(g, 
    with_labels=False,
    cmap=plt.get_cmap('RdBu'),
    node_color=scores,
    node_size=40,
    font_size=8)

plt.show()

And currently the output is as shown:

所有节点重叠的当前输出

This graph object itself has taken a relatively long time to generate and is computationally intensive, so ideally I wouldn't have to remake the graph from scratch.

However, I am fairly sure that the graph is drawn in the same order that the nodes were added to the graph object. I have searched for a way of changing the order that the nodes are stored within the graph object, but given directional graphs actually have an order, my searches always end up with answers showing me how to reverse the direction of a graph.

So, is there a way to dictate the order in which nodes are drawn, or alternatively, change the order that nodes are stored inside some graph object.

Potentially worthy of a second question, but the edges are also blocked out by the large number of nodes. Is there a way to draw the edges above the nodes behind them?

Piggybacking off Paul Brodersen's answer, if you want different nodes to be in the foreground and background, I think you should do the following:

For all nodes that belong in the same layer, draw the subgraph corresponding to the nodes, and set the , as follows:

pos = {...} # some dictionary of node positions, required for the function below
H = G.subgraph(nbunch)
collection = nx.draw_networkx_nodes(H, pos)
collection.set_zorder(zorder)

Do this for every group of nodes that belong in the same level. It's tedious, but it will do the trick. Here is a toy example that I created based on looking up this question as part of my own research

import matplotlib as mpl 
mpl.use('agg')
import pylab
import networkx as nx

G = nx.Graph()
G.add_path([1, 2, 3, 4]) 
pos = {1 : (0, 0), 2 : (0.5, 0), 3 : (1, 0), 4 : (1.5, 0)} 

for node in G.nodes():
    H = G.subgraph([node])
    collection = nx.draw_networkx_nodes(H, pos)
    collection.set_zorder(node)

pylab.plot([0, 2], [0, 0], zorder=2.5)

pylab.savefig('nodes_zorder.pdf', format='pdf')
pylab.close()

This makes a graph, and then puts the each node at a successively higher level going from left to right, so the leftmost node is farthest in the background and the rightmost node is farthest in the foreground. It then draws a straight line whose zorder is 2. As a result, it comes in front of the two left nodes, and behind the two right nodes. Here is the result.

在此处输入图像描述

draw is a wrapper around draw_networkx_nodes and draw_networkx_edges . Unlike draw , the two functions return their respective artists ( PathCollection and LineCollection , IIRC). These are your standard matplotlib artists, and as as such their relative draw order can be controlled via their zorder attribute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM