How to add an additional edge between nodes that already have edges? - python

I have a Graph object and between each pair of nodes that already has an edge, I would like to add an additional edge? Is there a way to do this without brute force looping through all the edges?

A simple way to do this is:
temp = nx.Graph(our_graph)
new_graph = nx.MultiGraph(temp)
new_graph.add_edges_from(temp.edges)

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 to build graph paths from list of nodes in NetworkX

What I am trying to do is build a graph in NetworkX, in which every node is a train station. To build the nodes I did:
G = nx.Graph()
G.add_nodes_from(trains['Stopping place'].unique())
which (at least as it looks like) it's working.
Now, since for each line I have the stops in sequence, I built my paths like so:
stops_by_line = ((belgium_trains.sort_values(['Train number','Actual arrival datetime']).groupby('Train number'))['Stopping place'].apply(list).to_dict())
paths = ([tuple(val) for val in stops_by_line.values()])
and the variable looks like this:
[('HERGENRATH',
'CHENEE',
'ANGLEUR',
'LIEGE-GUILLEMINS',
'ANS',
'LEUVEN',
'HERENT',
'VELTEM',
'ERPS-KWERPS',
'KORTENBERG',
'NOSSEGEM',
'ZAVENTEM',
'DIEGEM',
'HAREN-ZUID',
'SCHAARBEEK',
'BRUSSEL-NOORD',
'BRUSSEL-CONGRES',
'BRUSSEL-CENTRAAL',
'BRUSSEL-KAPELLEKERK',
'BRUSSEL-ZUID'),
(...other ordered tuples of stops),...)]
Now my question is, since all of these elements are also node names, how can I build the edges using these tuples sequentially (for example add an edge between BRUSSEL-NOORD and BRUSSEL-CONGRES, then from BRUSSEL-CONGRES to BRUSSEL-CENTRAAL and so on)?
You can simply use the add_path method in a loop:
for path in paths:
nx.add_path(G, path)
Sidemark, if you add an edge (like e.g. above), then networkx also directly adds the respective nodes to the graph. So probably (if all stops are covered by some train) you don't need to add the nodes manually before.

Is it possible to draw in networkx using current node placement in figure?

I have matlibplot and networkx. I have generated graph and i want to remove edges, but I want also to have vertices in the same place. Is it possible with this python stack containing: networx and matlibplot? For example
self.figure.clf()
self.axes = self.figure.add_subplot(111)
print 'generate random graph'
self.G.remove_edge(0,1)
self.G.remove_edge(0,2)
nx.draw(self.G, node_color='c',edge_color='k', with_labels=True, ax=self.axes)
self.canvas.draw()
here I want to remove edges, but after nx.draw node placement is not in the same position
In networkX, the function draw have a parameter pos and it can take a dictionary to specify each node's position.
Refer the document here: https://networkx.github.io/documentation/networkx-1.10/reference/generated/networkx.drawing.nx_pylab.draw.html#draw
Further more, to automatically generate such a dictionary, networkX provides many ways organized in the layout section.
Refer the document here: https://networkx.github.io/documentation/development/reference/drawing.html?highlight=layout#module-networkx.drawing.layout
If you draw two graphs with the same position dictionary, all the nodes will be at the same position.

networkx best practice getting edge attribute value while iterating over edges

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'):
...

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.

Categories