Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use user-defined class object as a networkx node?

Class point is defined as (there are also some methods, atributes, and stuff in it, but this is minimal part):

class point():
    def ___init___(self, x, y):
        self.x = x
        self.y = y

So, I saw this question, but when I tried applying it, it returns an error:

G = nx.Graph()
p = point(0,0)
G.add_node(0, p)

NetworkXError: The attr_dict argument must be a dictionary.

If i use

G = nx.Graph()
p = point(0,0)
G.add_node(0, data = p)

I don't get an error, but when i try to access the x-coordinate, it turns out it didn't save it as a point.

G[0].x

returns: AttributeError: 'dict' object has no attribute 'x'

doing

G = nx.Graph()
G.add_node(0, data = point(0,0))
G[0]

returns: {}

which means it still saves it as a dictionary.

I saw I can make my points hashable, and use these objects as nodes, so i added atribute id, since points are going to move. I added this to the class, and __repr__ for nice drawing of the graphs:

def __hash__(self):
    return self.id_n
def __cmp__(self, p):
    if self.id_n < p.id_n: return -1
    elif self.id_n == p.id_n: return 0
    else: return 1
def __eq__(self, p):
    if p.id_n == self.id_n: return True
    else: return False
def __repr__(self):
    return str(self.id_n) 

but that is a bit wierd, since I don't understand how to select a node then, by

G[<what should i put here?>]

So, question is, what is a proper way to do this?

I hoped to be able to use something like

G[node_id].some_method(some_args)
like image 324
Luka Petrović Avatar asked Jan 31 '18 13:01

Luka Petrović


People also ask

Which data type can be used as the content of a node in NetworkX?

In NetworkX, nodes can be any hashable object e.g., a text string, an image, an XML object, another Graph, a customized node object, etc. Python's None object is not allowed to be used as a node.

What is Nbunch in NetworkX?

nbunch. An nbunch is a single node, container of nodes or None (representing all nodes). It can be a list, set, graph, etc.. To filter an nbunch so that only nodes actually in G appear, use G.

Can NetworkX handle large graphs?

For NetworkX, a graph with more than 100K nodes may be too large. I'll demonstrate that it can handle a network with 187K nodes in this post, but the centrality calculations were prolonged. Luckily, there are some other packages available to help us with even larger graphs.


1 Answers

edit - in the below, replace G.node[] with G.nodes[] - in version 2.4 G.node was deprecated.

You're looking at G[0]. But that's not what you want. G[0] contains the information about neighbors of node 0 and the attributes of the edges, but nothing about the attributes of node 0.

class point():
    def __init__(self, x, y):
        self.x = x
        self.y = y

import networkx as nx
G = nx.Graph()
p0 = point(0,0)
p1 = point(1,1)

G.add_node(0, data=p0)
G.add_node(1, data=p1)
G.add_edge(0,1, weight=4)
G[0]
> AtlasView({1: {'weight': 4}})  #in networkx 1.x this is actually a dict. In 2.x it is an "AtlasView"

For networkx there is an expectation that a node may have a lot of data associated with it. In your case, you only have a single piece of data, namely the point. But you could have also assigned a color, a weight, a time, an age, etc. So networkx is going to store all the attributes in another dictionary, but that dictionary is accessed through G.node[0] rather than G[0].

G.node[0]
> {'data': <__main__.point at 0x11056da20>}
G.node[0]['data'].x
> 0

Notice that data in your input becomes the string 'data'.

It might be better to enter the nodes like G.add_node(0, x=0, y=0) and then you can access the entries as G.node[0]['x'].

like image 179
Joel Avatar answered Sep 20 '22 15:09

Joel