5

So I'm using a networkX graph to represent some information. This information is represented by different object types (for example, ColorNode and ShapeNode).

Some of the processing that is done on this graph requires me to extract out a specific type of node. Every time I need to do this, I do something along the lines of the code below.

colornodes = []
for node in graph.nodes():
    if isinstance(node, ColorNode):
        colornodes.append()

While this works, I feel like this is a situation that would arise often when working with graphs and I am re-inventing the wheel there. Essentially, I would like to know if there is a nicer way of doing this.

xyzen
  • 353
  • 2
  • 12
  • @Joel thanks for pointing that out. If I click "that solved my problem" would question still be viewable by others? Asking primarily because the alternate method in Kikohs answer is quite valuable and I wouldn't want to loose that. – xyzen Nov 11 '15 at 23:27
  • Yes - it would look something like this: https://stackoverflow.com/questions/12231644/js-replace-not-working-on-string?lq=1 This question and its answers would remain and a link to the other page would appear prominently (and the other page would have a link on the sidebar to this page). – Joel Nov 12 '15 at 00:15

2 Answers2

11

Instead of defining your own type and always check with isinstance (which is painfully slow) I suggest another approach.

You can have a look at this answer for the classic node/edge filtering.

However I found another trick which may come handy for your specific case.

If you define an attribute that represents the node type, you can query nodes having that specific attribute using the builtin get_node_attributes function. The trick is that it only returns nodes that really define the attribute:

import networkx as nx

G = nx.complete_graph(10)
G.node[0]['ColorNode'] = True  # right-hand side value is irrelevant for the lookup
G.node[1]['ColorNode'] = True
G.node[2]['ShapeNode'] = True
G.node[3]['ShapeNode'] = True

shape_nodes = nx.get_node_attributes(G, 'ShapeNode').keys()
color_nodes = nx.get_node_attributes(G, 'ColorNode').keys()

print('Shape node ids: {}'.format(shape_nodes))
print('Color node ids: {}'.format(color_nodes))

Output:

Shape node ids: [2, 3]
Color node ids: [0, 1]

Of course if your graph is big or static, you should keep the id lists for fast querying!

Community
  • 1
  • 1
Kirell
  • 9,228
  • 4
  • 46
  • 61
-4

instead of graph.nodes(), you can use xpath.

hiro protagonist
  • 44,693
  • 14
  • 86
  • 111
sneha
  • 7
  • 1
  • 9
  • Sorry, I could be missing something obvious here, but is xpath something that is part of networkx? I can't seem to find anything in the networkx doucmentation related to xpath – xyzen Nov 11 '15 at 05:37
  • yes like ---- for node in graph.xpath(.... ) – sneha Nov 11 '15 at 06:26
  • Would you clarify your answer @sneha – Abdallah Sobehy Nov 11 '15 at 16:38
  • @sneha if `graph` is a networkx graph, then `graph.xpath` is undefined. – Joel Nov 11 '15 at 23:00
  • for example:def edges(): for node in root.xpath('//n:node', namespaces = { 'n' : root.nsmap[None] }): node_id = int(node.attrib['id']) for edge in node.xpath('./n:children/n:nodeRef/@rid', namespaces = { 'n' : root.nsmap[None] }): yield (node_id, int(edge)) – sneha Nov 12 '15 at 02:48