I'm using NetworkX to create a weighted graph (not a digraph). Each node has a node name and a number of edges that have a weight. The weights are always positive, non-zero integers.
What I'm trying to do is get a list of tuples where each tuple represents a node in the graph (by name) and the weighted degree of the node.
I can do something like this:
the_list = sorted(my_graph.degree_iter(),key=itemgetter(1),reverse=True)
But this doesn't appear to be taking the weighting of each node into account. Each node may have a different weight for every edge (or they may be the same, there's no way to know).
Do I need to write a function to do this manually? I've been coming through the NetworkX docs and am coming up empty on a built-in way to do this (but maybe I'm overlooking it).
If I have to write the function myself, I'm assuming I use the size() method with the weight flag set. That seems to only give me the sum of all the weights in the graph though.
Any help is greatly appreciated.
You can use the Graph.degree() method with the weight= keyword like this:
In [1]: import networkx as nx
In [2]: G = nx.Graph()
In [3]: G.add_edge(1,2,weight=7)
In [4]: G.add_edge(1,3,weight=42)
In [5]: G.degree(weight='weight')
Out[5]: {1: 49, 2: 7, 3: 42}
In [6]: G.degree(weight='weight').items()
Out[6]: [(1, 49), (2, 7), (3, 42)]
Related
I'm trying to detect some minimal patterns with properties in random digraphs. Namely, I have a list called patterns of adjacency matrix of various size. For instance, I have [0] (a sink), but also a [0100 0001 1000 0010] (cycle of size 4), [0100, 0010, 0001, 0000] a path of length 3, etc.
When I generate a digraph, I compute all sets that may be new patterns. However, in most of the case it is something that I don't care about: for instance, if the potential new pattern is a cycle of size 5, it does not teach me anything because it has a cycle of length 3 as an induced subgraph.
I suppose one way to do it would look like this:
#D is the adjacency matrix of a possible new pattern
new_pattern = True
for pi in patterns:
k = len(pi)
induced_subgraphs = all_induced_subgraphs(D, k)
for s in induced_subgraphs:
if isomorphic(s, pi):
new_pattern = False
break
where all_induced_subgraphs(D,k) gives all possible induced subgraphs of D of size k, and isomorphic(s,pi) determines if s and pi are isomorphic digraphs.
However, checking all induced subgraphs of a digraph seems absolutely horrible to do. Is there a clever thing to do there?
Thanks to #Stef I learned that this problem has a name
and can be solved using on netwokx with a function described on this page.
Personally I use igraph on my project so I will use this.
I'm trying to save networkx DiGraph by preserving nodes' attributes.
I have tried with nx.write_weighted_edgelist, nx.write_edgelist and nx.write_weighted_edgelist , and after trying (and also looking at https://networkx.org/documentation/networkx-1.10/reference/readwrite.html) I know that both adjacency and edge lists does not preserve nodes' attributes.
Now I have seen also the other options in the networkx link, but I don't understand if other commands preserve attributes, and I need to be sure that it works (my code need to create and save more than 5000 graphs and it takes almost a day to run).
So which is the best way to save a graph and preserve nodes' attributes?
First, note that you are using an outdated version of the NetworkX docs; you should always use the stable version.
One format which is guaranteed to preserve node data is the pickle (although this is deprecated in NetworkX 2.6, it is currently usable):
In [1]: import networkx as nx
In [2]: G = nx.Graph()
In [3]: G.add_node("A", weight=10)
In [4]: nx.write_gpickle(G, "test.gpickle")
In [5]: H = nx.read_gpickle("test.gpickle")
In [6]: H.nodes(data=True)
Out[6]: NodeDataView({'A': {'weight': 10}})
The GML format should also work for most datatypes:
In [8]: nx.write_gml(G, "test.gml")
In [9]: H = nx.read_gml("test.gml")
In [10]: H.nodes(data=True)
Out[10]: NodeDataView({'A': {'weight': 10}})
GEXF works as well:
In [12]: nx.write_gexf(G, "test.gexf")
In [13]: H = nx.read_gexf("test.gexf")
In [14]: H.nodes(data=True)
Out[14]: NodeDataView({'A': {'weight': 10, 'label': 'A'}})
So you have several options and can decide based on performance and support for the specific attribute data you are trying to save.
Is there a way of removing reversible edges in a graph. For instance, let's say the following graph
import networkx as nx
G=nx.DiGraph()
G.add_edge(1,2)
G.add_edge(2,3)
G.add_edge(2,1)
G.add_edge(3,1)
print (G.edges())
[(1, 2), (2, 3), (2,1), (3,1)]
I want to remove (2,1) and (3,1), since I want the graph to be directed in just one direction. I know you can remove self-loops by using G.remove_edges_from(G.selfloop_edges()) but that's not the case here. The output I am looking for would be [(1, 2), (2, 3)]. Is there a way to remove this edges once the graph is created either by networkx or by other graph tool such as cytoscape?.
Method 1:
remove duplicate entries in edgelist -> remove everything from graph -> add back single edges => graph with single edges
Edges are stored as tuples. You could lose index information via temporary conversion to sets. You could then lose duplicate tuples, again, through temporary conversion to a set. After conversion back to a list, you have your list of edges, with duplicate entries removed, like so:
stripped_list = list(set([tuple(set(edge)) for edge in G.edges()]))
Then remove all edges from the graph that are currently there, and add back those that are in the list just created:
G.remove_edges_from([e for e in G.edges()])
G.add_edges_from(stripped_list)
Method 2:
find duplicate edges -> remove only those from graph => graph with single edges
again, losing positional information via conversion to sets:
set_list = [set(a) for a in G.edges()] # collect all edges, lose positional information
remove_list = [] # initialise
for i in range(len(set_list)):
edge = set_list.pop(0) # look at zeroth element in list:
# if there is still an edge like the current one in the list,
# add the current edge to the remove list:
if set_list.count(edge) > 0:
u,v = edge
# add the reversed edge
remove_list.append((v, u))
# alternatively, add the original edge:
# remove_list.append((u, v))
G.remove_edges_from(remove_list) # remove all edges collected above
As far as I know, networkx does not store the order that edges were added in, so unless you want to write further logic, you either remove all duplicate edges going from nodes with lower number to nodes with higher number, or the other way round.
I need to label a tree's nodes by the order in which the nodes are visited during a depth first search. I have to implement it in Python. I'm trying to use networkx lib but still have no idea about how to do it. Do you guys have any idea about how to use it ? Or should I try to implement it by myself ?
Cheers, GP
Try not implement well know algorithms if they exist in the library. There you have a link to the doc of basic traversal algorithms.
http://networkx.github.io/documentation/latest/reference/algorithms.traversal.html
Have fun :)
Well, if you create a new graph,
>>> import networkx as nx
>>> g = nx.DiGraph()
And you add some edges,
>>> g.add_edges_from([(0,1),(1,2),(0,3),(3,4),(3,5),(5,6)]) # etc
You can use dfs_edges() to traverse and to view the order of traversal.
>>> nodes = nx.dfs_edges(random_g, node_) # This creates an edges iterator
>>> nodes.next()
(0, 1)
>>> nodes.next()
(1, 2)
>>> nodes.next()
(0, 3)
>>>
And if you want you can grab the output from calls to .next(), to ascertain the nodes which are getting visited.
For example, (excluding the first node, 0),
>>> for n in nodes:
... print n[1]
...
1
2
3
4
5
6
>>>
I am using python with networkx package. I need to find the nodes connected to out edges of a given node.
I know there is a function networkx.DiGraph.out_edges but it returns out edges for the entire graph.
I'm not a networkx expert, but have you tried networkx.DiGraph.out_edges, specifying the source node?
DiGraph.out_edges(nbunch=None, data=False)
Return a list of edges.
Edges are returned as tuples with optional data in the order (node,
neighbor, data).
If you just want the out edges for a single node, pass that node in inside the nbunch:
graph.out_edges([my_node])
The simplest way is to use the successors() method:
In [1]: import networkx as nx
In [2]: G=nx.DiGraph([(0,1),(1,2)])
In [3]: G.edges()
Out[3]: [(0, 1), (1, 2)]
In [4]: G.successors(1)
Out[4]: [2]