2
votes

I have a data in the text file and I want to create an undirected weighted graph as I read it from the file. Data consists of tweets. For every word in the tweet I create a node in the graph. For every other word I create an edge between them and add 1 to their weight. So the weight of the edge should be the number of occurrences of two words across all tweets.

I create a graph:

graph=igraph.Graph();

I get edge between two nodes with their using ID:

edge=graph.es.select(_source=id1,_target=id2);

However this won't find the edge from id2 to id1, even if the graph is undirected. So I used the following hack:

edge1=graph.es.select(_source=id1,_target=id2);
edge2=graph.es.select(_source=id2,_target=id1);

if (len(edge1)>len(edge2)):
   edge=edge1;
else:
   edge=edge2;

My first question: is there a better way to do this?

However my main problem is updating weights. After I found the edge using the above code I try to update it's weight using:

if (len(edge)==0):
   graph.add_edge(id1,id2);
   edge=graph.es.select(_source=id1,_target=id2);
   edge["weight"]=1;
#else add weight
else:
    print edge.attributes();
    print edge["weight"];
    edge["weight"][0]=edge["weight"][0]+1;

However I get the following error:

 ...
 ['weight']
 [None]
 Traceback (most recent call last):
   File "/home/ivan/workspace/Twitter/process/MovieGraph.py", line 145, in <module>
     processTweet(g,words);
   File "/home/ivan/workspace/Twitter/process/MovieGraph.py", line 87, in processTweet
     edge["weight"][0]=edge["weight"][0]+1;
 TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'

I tried to debug, but it looks like the edge exists but the weight is not defined. How is it possible? Thank you.

1

1 Answers

8
votes

Regarding finding an edge between vertices id1 and id2: using get_eid is probably faster because it is implemented entirely in C. You can do something like this:

eid = graph.get_eid(source, target)
edge = graph.es[eid]

(The second line is needed because get_eid returns the ID of the edge only, not the edge itself). get_eid also handles undirected graphs properly; in other words, it will always look in both directions for undirected graphs.

However, note that get_eid throws an exception if the edge you are looking for does not exist, so you should also catch the exception and add the edge:

try:
    eid = graph.get_eid(source, target)
except igraph.InternalError:
    eid = graph.ecount()
    graph.add_edge(source, target, weight=0)

The except branch makes use of the fact that the ID of a newly added edge will always be equal to the number of edges in the graph before the addition, since edges are always numbered consecutively from zero. Note that the call to add_edge also sets the value of the weight attribute to zero, so you can simply increase the weight after the try..except block as follows:

edge["weight"] += 1