Is there an equivalent of this igraph R function in Python igraph?
graph_from_data_frame(d, directed = TRUE, vertices = NULL)
This function creates an igraph graph from one or two data frames
containing the (symbolic) edge list and edge/vertex attributes.
Python does not have data frames so there is no direct equivalent. The closest equivalent could be Graph.DictList, which creates a graph from a list of dictionaries, or Graph.TupleList, which is the same for a list of tuples.
Right now you can use this:
from igraph import Graph
g = Graph.DataFrame(edges, directed=False, vertices=vertices, use_vids=False)
where "edges" is a Pandas dataframe with the edges, vertices are the names that will be used in each vertex, and use_vids if you want to assign indexes to name the edges instead of using the "vertices" data
https://igraph.org/python/api/0.9.7/igraph.Graph.html#DataFrame
Related
I am not sure I understand how Networkit handles the names of the nodes.
Let's say that I read a large graph from an edgelist, using another Python module like Networkx; then I convert it to a Network graph and I perform some operations, like computing the pairwise distances. A simple piece of code to do this could be:
import networkx as nx
import networkit as nk
nxG=nx.read_edgelist('test.edgelist',data=True)
G = nk.nxadapter.nx2nk(nxG, weightAttr='weight')
apsp = nk.distance.APSP(G)
apsp.run()
dist=apsp.getDistances()
easy-peasy.
Now, what if I want to do something with those distances? For examples, what if I want to plot them against, I don’t know, the weights on the paths, or any other measure that requires the retrieval of the original node ids?
The getDistances() function returns a list of lists, one for each node with the distance to every other node, but I have no clue on how Networkit maps the nodes’ names to the sequence of ints that it uses as nodes identifiers, thus the order it followed to compute the distances and store them in the output.
When creating a new graph from networkx, NetworKit creates a dictionary that maps each node id in nxG to an unique integer from 0 to n - 1 in G (where n is the number of nodes) with this instruction.
Unfortunately, this mapping is not returned by nx2nk, so you should create it yourself.
Let's assume that you want to get a distance from node 1 to node 2, where 1 and 2 are node ids in nxG:
import networkx as nx
import networkit as nk
nxG=nx.read_edgelist('test.edgelist',data=True)
G = nk.nxadapter.nx2nk(nxG, weightAttr='weight')
# Get mapping from node ids in nxG to node ids in G
idmap = dict((id, u) for (id, u) in zip(nxG.nodes(), range(nxG.number_of_nodes())))
apsp = nk.distance.APSP(G)
apsp.run()
dist=apsp.getDistances()
# Get distance from node `1` to node `2`
dist_from_1_to_2 = dist[idmap['1']][idmap['2']]
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.
I'd like to specify the coordinates of the vertices of a graph in graph-tool in an efficient way.
Given a csv which looks like:
Node,X,Y
1,2.5,3.8
2,3.4,2.9
...
I'd like graph-tool to plot vertex 1 at position (2.5,3.8) etc...
A non efficient solution is given in :
Explicit vertex position in python graph-tool , so I can basically use a for loop over all my coordinates and save them in the property map 'pos'. If my graph is 'g' and my csv is read using pandas in the dataframe 'coordinates', I can do:
for i in range(1,numnodes+1):
pos[g.vertex(i)] = (coordinates.values[i-1,1],coordinates.values[i-1,2])
The problem is that my number of nodes, numnodes is big (~10^7), and this can take some time.
Is there a more efficient way to do this operation by inputting directly the data in the property map 'pos' ?
I found an answer to my question, an efficient way to do this is to use the .set_2d_array() function;
pos.set_2d_array(coordinates[['X','Y']].values.T)
does the trick.
Here ".T" is the transposition function, part of the numpy library.
I would try this:
pos = coordinates[['X','Y']].values
if graph-tool accepts numpy arrays, otherwise:
pos = [tuple(t) for t in coordinates[['X','Y']].values]
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.
What if I need to create a graph in igraph and add a bunch of edges, but the edges have associated attributes? It looks like .add_edges can only take a list of edges without attributes, so I've been adding them one by one with .add_edge
graph.add_edge('A','B',weight = 20)
Here A and B are names of nodes
You can assign the attributes later; e.g.:
graph.es["weight"] = range(g.ecount())
This will assign weights to all the edges at once. If you want to assign attributes to only a subset of the edges, index or slice the edge sequence (g.es) in however you want:
graph.es[10:20]["weight"] = range(10)