networkx best practice getting edge attribute value while iterating over edges - python

Given a list of edges (or a generator). What is the most readable way to identify edges with a certain attribute value? For example all edges with an 'edge_type' of 'foo'?
Currently, my code looks like this:
for edge in nx_graph.out_edges(my_node):
edge_type = nx_graph[edge[0]][edge[1]]['edge_type']
if edge_type == 'foo':
...
Due to the many brackets this is not very easy to read...
A slightly more readable approach:
for edge in G.edges_iter(data=True):
if edge[2]['edge_type']=='foo':
...
Yet it is still not very clear (especially the [2] ). Also, I am not sure how to use it with out_edges()

Here's an option
for edge in ((u,v,data) for u,v,data in G.edges_iter(data=True) if data['edge_type']=='foo'):
...

Related

Networkx tools in Python

Hi i am still quite new to networkx python.
does anyone know how i can get all of the intersection?
Intersection nodes are the red circled. This is for undirected Graph, I would also very keen to know if there is also a way to get intersection for directed graph
Once i got the intersection, I also would like to get the start and the end node. the reason is I wanted to put different group to the path (from start node to end node)
Can I achieve this result too :<
If with intersections you mean nodes with more than two neighbors than you can use that exact logic like
intersections = [node for node in G.nodes() if len(list(G.neighbors(node)))>2]
H = G.copy()
H.remove_nodes_from(intersections)
components = nx.connected_components(H)
For "spotting" intersection you can issue them an attribute like this:
intersections_subgraph = nx.subgraph(G, intersetions)
nx.set_node_attributes(intersections_subgraph, True, 'intersection')
Adding intersections back into the sections should works by looping through the intersections neighbors and adding the intersection to the section the neighbors are in.
For sorting I would loop through the section to find a start point (only one edge/neighbor) and then move from node to node. Note that sets are always unordered so you will have to switch over to an ordered structure like a list.
Ill leave implementing those to you

How do I find the number of vertices in a graph created by iGraph in python?

I'm writing a function that receives a graph as input.
The very first thing I need to do is determine the order of the graph (that is, the number of vertices in the graph).
I mean, I could use g.summary() (which returns a string that includes the number of vertices), but then I'd have parse the string to get at the number of vertices -- and that's just nasty.
To get the number of edges I'm using len(g.get_edgelist()), which works. But there is no g.get_vertexlist(), so I can't use the same method.
Surely there is an easy way to do this that doesn't involve parsing strings.
g.vcount() is a dedicated function in igraph that returns the number of vertices. Similarly, g.ecount() returns the number of edges, and it is way faster than len(g.get_edgelist()) as it does not have to construct the full edge list in advance.
As some functions in igraph have been renamed in meantime, I found the answers here out of date. What the docs suggest now is calling
gorder(g)
which works for me. Analogy for ecount is
gsize(g) # vcount(g) still works, but not g.vcount()
It's useful to note that help pages are cleverly redirected, so
?vcount
brings you to gorder docs etc.
g.vs should return the sequence of vertices as an igraph.VertexSeq object:
>>> from igraph import Graph
>>> g = Graph.Formula("A-B")
>>> g.vs["name"]
['A', 'B']
>>> len(g.vs)
2
>>> g.vcount()
2
Edit: As #Tamas mentions below, g.vcount() will also return the number of vertices. Example edited to account for this.

How to get edge indices from selection?

Is there's a way to get the indices properly from a Pymel/Maya API function?
I know Pymel has a function called getEdges() however according to their docs this get's them from the selected face, however I just need them from the selected edges.
Is this possible?
While your answer will work theodox, I did find a much simpler resolution, after some serious digging!
Turns out, hiding and not very well documented, was a function ironically called indices(), I did search for this but nothing came up in the docs.
Pymel
selection[0].indices()[0]
The above will give us the integer of the selected edge. Simple and elegant!
Do you mean you just the expanded list of selected edges? That's just FilterExpand -sm 32 or cmds.filterExpand(sm=32) or pm.filterExpand(sm=32) on an edge selection. Those commands are always strings, you grab the indices out them with a regular expression:
# where objs is a list of edges, for example cmds.ls(sl=True) on an edge selection
cList = "".join(cmds.filterExpand( *objs, sm=32))
outList = set(map ( int, re.findall('\[([0-9]+)\]', cList ) ) )
which will give you a set containing the integer indices of the edges (I use sets so its easy to do things like find edges common to two groups without for loops or if tests)

Find all vertices with the same edge attribute

I would like to find all vertices (vertex id's) sharing the same edge attribute (so there can be tons of vertices like this) by using Igraph. This would be very convenient when I want to find all "villages" (the vertices of my graph) on a "road", let's say "Route 69" (an edge attribute).
Is there a simple way in Igraph to do this? Maybe I've overcomplicated it.
Actually what I need is the opposite of: g.es.select(_within=g.vs[2:5]) or
>>> men = g.vs.select(gender="m")
>>> women = g.vs.select(gender="f")
>>> g.es.select(_between=(men, women))
because I know the edge attribute but I don't know the vertices.
I will select the edge and hope that it will return all related vertices.
Maybe I'm only tired now, but I don't find my way around this problem. I appreciate if somebody helps me out with the right way. Or maybe there is a method I miss in tutorial and documentation. It smells like there is a very simple method to this. Thank you in advance for any advice!
First, select all the edges on Route 69:
edges = g.es.select(name="Route69")
Then iterate through the selected edges and collect the endpoints of the vertices:
vertices = set()
for edge in edges:
vertices.update(edge.tuple)
This will give you a set containing the vertex IDs of all the vertices that are incident on at least one edge with name Route69. If you need a VertexSeq, you can simply do this:
vertices = g.vs[sorted(vertices)]
You should be able to do the following:
r69edges = g.es.select(name_eq='Route69') #Select all edges where name=='Route69'
sg = r69edges.subgraph() #Create a subgraph containing only the selected edges (and attached vertices)
village_verts = sg.vs.select(name_eq='villages') #Select the vertices where name=='villages'
This assumes that 'villages' and 'Route69' are stored in an attribute called 'name' on the vertices and edges... Adjust appropriately to match your attributes.
Of course - you can squash this all into one line if you want:
village_verts = g.es.select(name_eq='Route69').subgraph().vs.select(name_eq='villages')
Not sure if this is the most efficient way (though I'm not seeing any shortcuts in the documentation), but it should get you what you're after.

Double linking array in Python

Since I'm pretty new this question'll certainly sound stupid but I have no idea about how to approach this.
I'm trying take a list of nodes and for each of the nodes I want to create an array of predecessors and successors in the ordered array of all nodes.
Currently my code looks like this:
nodes = self.peers.keys()
nodes.sort()
peers = {}
numPeers = len(nodes)
for i in nodes:
peers[i] = [self.coordinator]
for i in range(0,len(nodes)):
peers[nodes[i%numPeers]].append(nodes[(i+1)%numPeers])
peers[nodes[(i+1)%numPeers]].append(nodes[i%numPeers])
# peers[nodes[i%numPeers]].append(nodes[(i+4)%numPeers])
# peers[nodes[(i+4)%numPeers]].append(nodes[i%numPeers])
The last two lines should later be used to create a skip graph, but that's not really important. The problem is that it doesn't really work reliably, sometimes a predecessor or a successor is skipped, and instead the next one is used, and so forth. Is this correct at all or is there a better way to do this? Basically I need to get the array indices with certain offsets from each other.
Any ideas?
I would almost bet that when the error occurs, the values in nodes have duplicates, which would cause your dictionary in peers to get mixed up. Your code assumes the values in nodes are unique.

Categories