Indexing vertex name - python

I am using python igraph version 0.6.5. I am bit unclear that in a code below:
g = igraph.Graph(directed=True)
g.add_vertex('A')
g.add_vertex('B')
g.add_vertex('A')
print g.vcount()
This gives me the count of vertex as 3 even though the vertex name 'A' is duplicated , why both vertex name 'A' are taken as 2 different vertex ? How can we index the vertex name ?

When you run g.add_vertex('A'), igraph does not add "A" as a vertex to the graph - it adds a completely new vertex and then assigns "A" to its name attribute, but names are not required to be unique in igraph. Internally vertices are represented by integers from zero to |V|-1, and the names are just attributes that are attacked to the vertices. So, if you want to make sure that you don't create duplicate vertices with the same name, you need to check whether a vertex exists with the same name:
try:
vertex = g.vs.find("A")
except ValueError:
g.add_vertex("A")
The name vertex attribute is treated specially by igraph as it is always backed by a dictionary that maps vertex names to the first vertex that has this name, so g.vs.find("A") is a fast operation (no need to scan the entire graph).

Related

Is there a way to preserve or track vertex correspondence after a series of vertex removals

In python-igraph, it seems to me that when you delete vertices from a graph, the vertices are renamed to using consecutive vertices from 0 to n.
To see what I mean, consider the following program:
from igraph import Graph
g=Graph.Full(4) # Vertex set is {0..3}
print g.neighbors(2) # Prints [0,1,3]
g.delete_vertices([1])
print g.neighbors(2) # Prints [0,1], but I'd want [0,3]
I could do my own manual bookkeeping, but is this already supported in the library somehow? Basically, I'd like to know after a series of vertex deletions, what the newly renamed vertices correspond to in the original graph (just like in the snippet above).
The easiest is to use the name vertex attribute to track the correspondence. Basically, if you assign names to the vertices, you can then use the names later wherever igraph expects a numeric vertex ID:
>>> g.vs["name"] = ["V{0}".format(i) for i in range(4)]
>>> g.vs[g.neighbors("V2")]["name"]
['V0', 'V1', 'V3']
>>> g.delete_vertices(["V1"])
>>> g.vs[g.neighbors("V2")]["name"]
['V0', 'V3']
The name attribute is indexed behind the scenes so looking up a vertex by name should have the same time complexity as a typical Python dict lookup.
For what it's worth, the vertex renumbering is a property of the underlying C library so there's not much that the Python interface can do about it.

Set list as vertex/edge attribute

I started using igraph for my B.Sc. thesis but i'm struggling when i try to assign a list as an attribute of a vertex.
Here's what i tried:
self.network.vs(node)[propertyName] = [0, value]
where network is my graph and node the name of the vertex.
When i try to access the elements i got an error (out of bounce) because the length of the list returned is 0.
How can I assign a list as a property of a vertex?
When you assign a list to a vertex property it is typically distributed over the vertices even though you give a specific vertex number. You have to specify that it is a list for a specific vertex. Such as the following.
self.network.vs(node)[propertyName] = [[0, value]]

IGraph python get neighbour Vetrices from Vertex

I have a graph and I want to implement a modification of the Page Rank algorithm. I am stuck on the following point. I don't know how to get all the neighboring vertices from a node.
Currently I am receiving the list of the edges using:
g.incident("a", mode="out")
This returns me the list of the edges indexes.
How can I get the vertex name from that?
For example I need to know that "a" is linked to "b" and "d"
g.neighbors("a", mode="out") will give you the vertex indices for the neighbors. You can then get the names as follows:
>>> neis = g.neighbors("a", mode="out")
>>> g.vs[neis]["name"]
But actually, if I were you, I would try to work with vertex indices as much as possible because it's way faster to work with the indices than with the names.

Python- How to retrieve the vertex set by its attributes

I am creating a graph with vertex and edges using networkx in python.
G= add_edge(vertex1,vertex2)
vertex1 and vertex2 are integers i.e.
G=add_edge(4,3),
G=add_edge(2,3)
etc..
Since, in python if we just give the edge list it creates the vertex and create the edges between the specified vertexes.
Now i need to add an attribute to the vertex of the graph i.e. i want to basically separate the vertex into groups based on the attribute.
Hence, i can do
G.node[your_vertex]['attribute'] = value
to add attribute to the already created graph G. #as suggested by BrenBarn.
Since there can be many different attributes and different values, how do i retrieve the vertex
By it's value.
By it's attribute.
This is described in the documentation:
G.node[1]['room'] = 714
You just do G.node[your_vertex]['attribute'] = value.

igraph fill in node attributes after importing edgelist in Ncol() format?

I'm not sure if this is a merge or two separate imports, or something I should reconsider entirely. I started using igraph originally after playing in gephi, where I would always do a 2-stage import, first the edges, then node-data. Is this a sensible strategy for igraph?
So, thanks to some recent help, I have just imported an edge list that looked something like this:
123123 321321 1
222222 333333 2
123123 333333 3
222222 321321 4
...with the import command
import igraph
g = igraph.Graph.Read_Ncol('edgelist.txt')
I'd like to add attributes to the nodes this edgelist import generated for me. These would be something like...
123123 "color:red" "community:1"
222222 "color:blue" "community:2"
321321 "color:red" "community:1"
333333 "color:red" "community:2"
How can I append this data to my current graph? I see many formats for importing sophisticated edgelists, but none for node-lists. What am I missing? Is there no automatic append-node-data-to-appropriate-node function?
If not, can someone recommend an easier way to appropriately fill node data to an existing graph?
My instinct was something like...
[g.vs["color"] = x for x in node_list.color if g.vs["name"] == node_list.name]
[g.vs["community"] = x for x in node_list.community if g.vs["name"] == node_list.name]
But this looks extremely kludgy.
Well, you are on the right track and yes, it is going to be a bit kludgy. It is kludgy because igraph is a plain C library deep down in its core, and it is much easier to work with numbers (i.e. vertex and edge IDs) in C instead of names (i.e. vertex and edge names). That's why igraph uses integers from zero upwards to refer to vertices and edges instead of their names, and that's why you have to jump through one extra hoop to get to the vertex itself from its name.
I would probably do the following:
Read the edge list using Graph.Read_Ncol. (You have already done that).
Build a dictionary that maps vertex names back to their IDs:
>>> id_mapping = dict((v, k) for k, v in g.vs["name"])
Read your attribute file into node_list. I assume that node_list.name gives me a list of vertex names and node_list.color gives me a list containing the corresponding colors. You can then do the following:
>>> for name, color in izip(node_list.name, node_list.color):
... g.vs[id_mapping[name]]["color"] = color
An alternative approach in the 3rd step is to use g.vs.find(name), which gives you a Vertex object that refers to the vertex with the given name. You can then assign the attribute to this vertex; e.g:
>>> for name, color in izip(node_list.name, node_list.color):
... g.vs.find(name)["color"] = color
In this case you won't need the id_mapping. Actually, igraph maintains a name-to-ID mapping in the background for the name vertex attribute only, and g.vs.find makes use of this mapping. The id_mapping-based approach is more useful if you want to use a different vertex attribute as the unique key for your vertices and not name.

Categories