How can i get directed tree from graph? - python

import networkx as nx
G = nx.Graph()
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(3,5)
G.add_edge(4,6)
G.add_edge(1,6)
G.add_edge(2,6)
G.add_edge(7,8)
G.add_edge(9,8)
mst=nx.prim_mst(G)# a generator of MST edges
I have got a tree. How can i get directed tree with root at 4?

To get the directed tree of breadth-first-search from node 4:
tree = nx.bfs_tree(G, 4)
To get the directed tree of depfth-first search from node 4:
tree = nx.dfs_tree(G, 4)
The graphs were generated this way:
import matplotlib.pyplot as plt
import networkx as nx
G = nx.Graph()
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(3,5)
G.add_edge(4,6)
G.add_edge(1,6)
G.add_edge(2,6)
G.add_edge(7,8)
G.add_edge(9,8)
tree = nx.bfs_tree(G, 4)
nx.draw(tree)
plt.savefig('/tmp/bfs_image.png')

It might be that #kalombo wants an oriented tree from the MST of G with root at node 4. In that case you will need to build the graph of the MST first. e.g.
T = nx.bfs_tree(nx.Graph(nx.prim_mst_edges(G)),4)

Related

I need to get the sum of the degrees of actor nodes in the graph with the actor nodes.this graph is bipartite graph which has actor and movie nodes

My code snippet for graph
import networkx as nx
from networkx.algorithms import bipartite
graded_graph= nx.Graph()
graded_graph.add_nodes_from(['a1','a5','a10','a11'], bipartite=0)
graded_graph.add_nodes_from(['m1','m2','m4','m6','m5','m8'], bipartite=1)
graded_graph.add_edges_from([('a1','m1'),('a1','m2'),('a1','m4'),('a11','m6'),('a5','m5'),
('a10','m8')])
l={'a1','a5','a10','a11'};r={'m1','m2','m4','m6','m5','m8'}
pos = {}
pos.update((node, (1, index)) for index, node in enumerate(l))
pos.update((node, (2, index)) for index, node in enumerate(r))
nx.draw_networkx(graded_graph, pos=pos,
with_labels=True,node_color='lightblue',alpha=0.8,style='dotted',node_size=500)
now i want to get the sum of the degrees of the actors nodes and movie nodes separately. if i use graded_graph.degrees(). the output that i get is list of the degrees for both actor and movie nodes. how can i separate them ?
Also how can i get the unique nodes for both movie and actor nodes?
import networkx as nx
from networkx.algorithms import bipartite
graded_graph= nx.Graph()
graded_graph.add_nodes_from(['actor_1','actor_5','actor_10','actor_11'], bipartite=0)
graded_graph.add_nodes_from(['mov_1','mov_2','mov_4','mov_6','mov_5','mov_8'], bipartite=1)
graded_graph.add_edges_from([('actor_1','mov_1'),('actor_1','mov_2'),('actor_1','mov_4'),
('actor_11','mov_6'),('actor_5','mov_5'), ('actor_10','mov_8')])
gd=graded_graph.to_directed()
dfDegree=pd.DataFrame([{'name':v[0][0],'degree':v[0][1],'type':v[0][0].split('_')[0]}
for v in list(zip(gd.degree)) ])
dfDegreeActor=dfDegree.query('type=="actor"')
dfDegreeMov=dfDegree.query('type=="mov"')
print(dfDegreeActor)
print(dfDegreeMov)

Combine edges when node degree is n in networkx

I have an undirected graph as follows:
import networkx as nx
import matplotlib.pyplot as plt
l = [('1','2'),('2','3'),('3','4'),('3','5'),('1','6'),('6','7'),('6','8'),('9','8')]
G=nx.Graph()
G.add_edges_from(l)
nx.draw_networkx(G,with_labels=True)
plt.show()
I want to combine edges when node satisfies degree=n(like 2). I need remove node 1,2 and 8,and connect 3-6 and 6-9 in my example. So I expect the results to be as follows.
How can I do it? Thanks in advaence
import networkx as nx
import matplotlib.pyplot as plt
l = [('1','2'),('2','3'),('3','4'),('3','5'),('1','6'),('6','7'),('6','8'),('9','8')]
G=nx.Graph()
G.add_edges_from(l)
# Select all nodes with only 2 neighbors
nodes_to_remove = [n for n in G.nodes if len(list(G.neighbors(n))) == 2]
# For each of those nodes
for node in nodes_to_remove:
# We add an edge between neighbors (len == 2 so it is correct)
G.add_edge(*G.neighbors(node))
# And delete the node
G.remove_node(node)
nx.draw(G,with_labels=True)

Plotting isolated nodes in NetworkX

import networkx as nx
import numpy as np
from scipy.sparse import coo_matrix #coordinate sparse matrices
A = np.zeros([4,4])
A[0,1] = A[1,2] = 1
S = coo_matrix(A)
edges = np.r_[[S.row], [S.col]].T
G = nx.Graph()
G.add_edges_from(edges)
nx.draw(G)
When I run that script, I get this:
But there are four nodes. How can I get the isolated fourth node to show?
By only adding the edges to the graph, networkx has no way of knowing about the additional vertices; all it's doing is adding the vertices of each edge that you're providing. If, instead, you explicitly add all vertices, then you're good to go:
G = nx.Graph()
G.add_nodes_from(range(len(A)))
G.add_edges_from(edges)
nx.draw(G)

Graph traversal with Networkx (Python)

I'm playing a bit with Networkx to manage a graph of dependencies.
Let's say I have this Graph which each letter represent a server
>>> G = nx.Graph()
>>> G.add_edge("A","B")
>>> G.add_edge("A","H")
>>> G.add_edge("H","C")
>>> G.add_edge("B","C")
>>> G.add_edge("B","D")
A
/ \
H B
/ / \
C C D
So here we can see that before starting A we need to start H and B and to start H we need to start C and then to start B wee need to start C and D
By fiddling a bit with Networkx I found that I can get that by doing a dfs traversal
print nx.dfs_successors(G,"A")
{A:[H,B], H:[C], B:[D] }
But I have a problem with that method. As you can see when there is two same letter in the tree, Networkx only chose to put one of them in the final structure (which is correct) But I need to have the complete structure
How can I force Networkx to add in the structure B:[D,C] ??
I want to precise that by doing
>>> nx.dfs_successors(G,"B")
{'B': ['C', 'D']}
So everything is "Internally" correct, it's just the dfs_successors that displays it not in the way I wish.
Thank you
Taking your code, your graph doesn't come out as you'd expect. If you do:
import pylab as p
import networkx as nx
G = nx.Graph()
G.add_edge("A","B")
G.add_edge("A","H")
G.add_edge("H","C")
G.add_edge("B","C")
G.add_edge("B","D")
nx.draw(G)
p.show()
you will see your graph as:
This is due to the logic of G.add_edge("A", "B"):
If G has no node of id "A", add it.
If G has no node of id "B", add it.
Connect "A" to "B" with a new edge.
Thus, you only create five nodes, not six as in your picture.
Edit
Networkx can take any hashable as value for a node, and in the graph it uses str(node) to label each circle. So we can simply define our own Node class (which you maybe want to call Server?) and give it the desired behavior.
import pylab as p
import networkx as nx
class Node(object):
nodes = []
def __init__(self, label):
self._label = label
def __str__(self):
return self._label
nodes = [Node(l) for l in ["A","B","C","C","D","H"]]
edges = [(0,1),(0,5),(5,2),(1,3),(1,4)]
G = nx.Graph()
for i,j in edges:
G.add_edge(nodes[i], nodes[j])
nx.draw(G)
p.show()
gives us
and so what you wanted.
I think what you are looking for is a topological sort https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.dag.topological_sort.html
This only works if you have a DAG (directed acyclic graph).
If so you can draw the tree you want too - like this:
import uuid
import networkx as nx
import matplotlib.pyplot as plt
G = nx.DiGraph()
G.add_edge("A","B")
G.add_edge("A","H")
G.add_edge("H","C")
G.add_edge("B","C")
G.add_edge("B","D")
order = nx.topological_sort(G)
print "topological sort"
print order
# build tree
start = order[0]
nodes = [order[0]] # start with first node in topological order
labels = {}
print "edges"
tree = nx.Graph()
while nodes:
source = nodes.pop()
labels[source] = source
for target in G.neighbors(source):
if target in tree:
t = uuid.uuid1() # new unique id
else:
t = target
labels[t] = target
tree.add_edge(source,t)
print source,target,source,t
nodes.append(target)
nx.draw(tree,labels=labels)
plt.show()
The drawing uses a label mapping to map the ids of the node to the original labels.

How do I get nodes from the specific edge in the networkx?

I want to compare nodes of different edges in the graph. How can I get the nodes(n1 and n2) from the edge(n1,n2)?
An edge in NetworkX is defined by its nodes, so I'm not really sure what you're asking here. A specific edge in the graph is just a tuple of nodes, with an optional weighting.
import networkx as nx
g = nx.Graph()
g.add_edge(1,2)
g.add_edge(2,3)
g.edges()
gives
[(1, 2), (2, 3)]
As you can see, the list of edges explicitly provides the nodes of each edge.
Update: Does this do what you want?
#!/usr/bin/python
import networkx as nx
import random
g = nx.Graph()
g.add_edges_from([(1,2),(2,3),(1,4),(2,5)])
random_edge = random.choice(g.edges())
print 'Randomly selected edge is:', random_edge
print 'Nodes are', random_edge[0], 'and', random_edge[1]
The answer to what I think was the intended question is:
graph = networkx.read_graphml('some_fully_loaded_graph.graphml')
edge0 = list(graph.edges(data=True))[0]
subgraph = graph.edge_subgraph([edge0[:2]])
nodes0 = list(subgraph.nodes(data=True))

Categories