[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [igraph] Simple syntax questions
From: |
Tamas Nepusz |
Subject: |
Re: [igraph] Simple syntax questions |
Date: |
Mon, 13 Apr 2009 20:14:10 +0100 |
Wondering if I could get an example. :-) I've been struggling to
figure it out.
Similar to http://igraph.sourceforge.net/igraphbook/igraphbook-creating.html#id2569368
but in Python.
Maybe you'll find the following page useful (it's fairly incomplete,
but good for a start) if you are using igraph from Python:
http://www.cs.rhul.ac.uk/home/tamas/development/igraph/tutorial/tutorial.html
It seems igraph wants you to tell how many nodes you have before you
can create an edge. Is this correct?
Yes, this is true. The reason is that igraph is a library written
primarily in C and the usage of C imposes somewhat stricter rules on
what can be done and what can't be done. One of the limitations is
that edges and vertices are identified by integers starting from zero
-- if I remember correctly, NetworkX is happy with arbitrary Python
objects as nodes and edges.
I'm pulling from a database and I have a loop ready to go that says
"x" (cat xyz, color blue) is related to "y" (cat abc, color red),
next record, "y" is related to "z". It all seems simple, but I
can't figure out how to make it happen.
In general, you need to construct a mapping (a Python dict) that maps
these string identifiers to non-negative integers. The way you do it
is absolutely up to you. I usually use a small helper class that
simulates a Python dict but automatically assigns new IDs to new
vertices. The helper class is as follows:
http://snipplr.com/view/13190/unique-id-sequence-class/
Using this helper class, you can do something like this:
names_to_idxs = UniqueIdGenerator()
edge_list = []
for row in my_data_source:
v1, v2 = names_to_idxs[row["source"]], names_to_idxs[row["target"]]
edge_list.append((v1, v2))
g = Graph(len(names_to_idxs), edge_list)
Note that I create the graph after I have read my data source
completely. The reason is that the more code you manage to push down
into the C core of igraph, the faster your code will be, and the code
above constructs the graph in one single pass in the C layer, which is
much faster than constructing the graph iteratively using add_vertices
and add_edges (which traverses many times back and forth between the
Python and the C layer). However, if you cannot do that for some
reason, you can do this:
names_to_idxs = UniqueIdGenerator()
edge_list = []
g = Graph(0)
for row in my_data_source:
v1, v2 = names_to_idxs[row["source"]], names_to_idxs[row["target"]]
if max(v1, v2) >= g.vcount():
g.add_vertices(max(v1, v2) - g.vcount() + 1)
g.add_edges([(v1, v2)])
I also want to be able to say that x is "red", y is "blue" and in
category "xyz". I want to tell it that the label and color of the
edge between "y" and "z" is "this" and "that".
This can be done with igraph as well, using vertex and edge
attributes; however, you will have to remember that you have to refer
to vertices and edges by their numeric indices instead of their names.
So, to say that vertex 0 is "red", you can do as follows:
g.vs[0]["color"] = "red"
g.vs acts as a list containing all the vertices. Indexing into g.vs
gives you a Vertex object that acts as a Python dictionary. Similarly.
g.es acts as a list containing all the edges and indexing into g.es
gives you an Edge object:
g.es[0]["weight"] = 2.0
It is a common task to look up vertices by names, though. You can
assign all the names to a "name" vertex attribute and then search for
vertices using names:
names = ["A", "B", "C", "D", "E"]
g.vs["name"] = names # assuming that you have five
vertices
At this point, g.vs.select(name="B") gives you all the vertices in a
list-like object whose name attribute equals "B", so you can do the
following:
my_node = g.vs.select(name="B")
my_node["color"] = "blue"
Hope this helps.
--
Tamas