Graph using python-igraph with attributes per node and edges

1

Speak up! I'm trying to create a graph using the Python-Igraph library. Each node would have an attribute, for example, in a graph of books whose nodes would be books and the attributes of those nodes would be:

titulo: nome_do_titulo
sinopse: descricao_do_livro
autor: nome_do_autor
prefacio: descricao_do_prefacio

and all these attributes of nodes would have edges linking to similar attributes of other nodes containing the weight of similarity between those attributes. Thus each node would have 4 edges for another node. I'm using python 3 and igraph.

The way I'm implementing it is as follows:

    g = Graph()
    g.vs["titulo"] = ['titulo1', 'titulo2', 'titulo3']
    g.vs["sinopse"] = ["sinopse1", "sinopse2", "sinopse3"]
    g.vs["autor"] = ["autor1","autor2","autor3"]
    g.vs["prefacio"] = ["prefacio1","prefacio2", "prefacio3"]

Now how to put the link between them I know that% s is used, but the Igraph site is a bit vague about it.

    
asked by anonymous 03.05.2017 / 23:39

1 answer

1

I did not know this igraph - apparently it's a library to work with graphs in Python.

So by taking a look at the documentation and experimenting with the Python interactive prompt (this is the secret to figuring out how to do things) - I understood the following:

The library does not support "1st class" for edges bound to specific attributes of the nodes - (or maybe the support it has is considered first class - I do not know :-))

But because the edges can have arbitrary attributes, you can put a "type" attribute on each edge - this way you will know which attribute it relates to. And, being complete, it perfectly supports more than one edge connecting the same pair of nodes, so you can have 2 edges relating two nodes you want to link by both title and author.

The only way to create an edge is to pass the numeric indexes of the nodes it is connecting to - I suggest you put a "type" attribute (it is always better to have your entire program - English - You never know when the project will grow to have international collaborators. But more important than being in English is to have all the variables and functions in the same language - started with Portuguese, continue with everything in Portuguese) - But then, to connect the nodes "0" and "1" by the title attribute, call

g.add_edge(source=0, target=1, tipo="titulo")

To find the indexes of the nodes you want to connect to each other, if you want an exact matches (==) of parameters, you can use the search with "find" in the object "g.vs" - for other searches you can use the filter with "if" from normal Python - and then use itertools.combinations to have all possible pairs of edges.

Example: Let's suppose you want to connect all nodes whose titles contain the word "narnia" - you can use a function like this:

import itertools 

def conecta(grafo, palavra, atributo):
   nos_relevantes = [no.index for no in grafo.vs if palavra in getattr(no, atributo, "").lower()]
   for origem, destino in itertools.product(nos_relevantes, 2):
       grafo.add_edge(source=origem, target=destino, tipo=atributo)

I think your question has been answered so far. (test at the interactive prompt these expressions, understand how itertools.product works, for example, etc ...)

Now, I have not seen enough of igraf to know if you're going to do what you want with the edges being distinguished only by this "type" attribute - now something you can certainly do is when you need to use edges specific, create copies of the graph, and filter to the new graph only those edges that are relevant:

from copy imoport deep_copy
g_titulo = deepcopy(g)
g_titulo.delete_edges([e.index for  in g_titulo.es if e["tipo"] != "titulo"])

In time: this igraph API to associate parameters to nodes from a list is a bit crazy - I do not know if that's the way you'd prefer to use it - I'd be more comfortable creating each node at once, passing all the bound parameters - is how we usually work in Python. Igraph supports this. That is, instead of creating the vertices as you are doing, you can do:

g = igraph.Graph()
dados = [{"titulo": "titulo1", "sinopse": "sinopse1", "autor": "autor1"}, {"titulo": "titulo2", "sinopse": "sinopse2", "autor": "autor2"}, ]
for dado in dados:
    g.add_vertex(**dado)

This makes it easy to put your initial data in a worksheet, save as CSV, and% Python% to create a node for each of your books, for example - and you do not have to worry - in parallel to the graph - in keeping lists with each attribute in the same order that the vertices are.

    
04.05.2017 / 02:22