DiGraph—Directed graphs with self loops


class DiGraph(incoming_graph_data=None, **attr)[source]

Base class for directed graphs.

A DiGraph stores nodes and edges with optional data, or attributes.

DiGraphs hold directed edges. Self loops are allowed but multiple (parallel) edges are not.

Nodes can be arbitrary (hashable) Python objects with optional key/value attributes. By convention None is not used as a node.

Edges are represented as links between nodes with optional key/value attributes.

  • incoming_graph_data (input graph (optional, default: None)) – Data to initialize graph. If None (default) an empty graph is created. The data can be any format that is supported by the to_networkx_graph() function, currently including edge list, dict of dicts, dict of lists, NetworkX graph, NumPy matrix or 2d ndarray, SciPy sparse matrix, or PyGraphviz graph.
  • attr (keyword arguments, optional (default= no attributes)) – Attributes to add to graph as key=value pairs.


Create an empty graph structure (a “null graph”) with no nodes and no edges.

>>> G = nx.DiGraph()

G can be grown in several ways.


Add one node at a time:

>>> G.add_node(1)

Add the nodes from any container (a list, dict, set or even the lines from a file or the nodes from another graph).

>>> G.add_nodes_from([2, 3])
>>> G.add_nodes_from(range(100, 110))
>>> H = nx.path_graph(10)
>>> G.add_nodes_from(H)

In addition to strings and integers any hashable Python object (except None) can represent a node, e.g. a customized node object, or even another Graph.

>>> G.add_node(H)


G can also be grown by adding edges.

Add one edge,

>>> G.add_edge(1, 2)

a list of edges,

>>> G.add_edges_from([(1, 2), (1, 3)])

or a collection of edges,

>>> G.add_edges_from(H.edges)

If some edges connect nodes not yet in the graph, the nodes are added automatically. There are no errors when adding nodes or edges that already exist.


Each graph, node, and edge can hold key/value attribute pairs in an associated attribute dictionary (the keys must be hashable). By default these are empty, but can be added or changed using add_edge, add_node or direct manipulation of the attribute dictionaries named graph, node and edge respectively.

>>> G = nx.DiGraph(day="Friday")
>>> G.graph
{'day': 'Friday'}

Add node attributes using add_node(), add_nodes_from() or G.nodes

>>> G.add_node(1, time='5pm')
>>> G.add_nodes_from([3], time='2pm')
>>> G.nodes[1]
{'time': '5pm'}
>>> G.nodes[1]['room'] = 714
>>> del G.nodes[1]['room'] # remove attribute
>>> list(G.nodes(data=True))
[(1, {'time': '5pm'}), (3, {'time': '2pm'})]

Add edge attributes using add_edge(), add_edges_from(), subscript notation, or G.edges.

>>> G.add_edge(1, 2, weight=4.7 )
>>> G.add_edges_from([(3, 4), (4, 5)], color='red')
>>> G.add_edges_from([(1, 2, {'color':'blue'}), (2, 3, {'weight':8})])
>>> G[1][2]['weight'] = 4.7
>>> G.edges[1, 2]['weight'] = 4

Warning: we protect the graph data structure by making G.edges[1, 2] a read-only dict-like structure. However, you can assign to attributes in e.g. G.edges[1, 2]. Thus, use 2 sets of brackets to add/change data attributes: G.edges[1, 2]['weight'] = 4 (For multigraphs: MG.edges[u, v, key][name] = value).


Many common graph features allow python syntax to speed reporting.

>>> 1 in G     # check if node in graph
>>> [n for n in G if n < 3]  # iterate through nodes
[1, 2]
>>> len(G)  # number of nodes in graph

Often the best way to traverse all edges of a graph is via the neighbors. The neighbors are reported as an adjacency-dict G.adj or G.adjacency()

>>> for n, nbrsdict in G.adjacency():
...     for nbr, eattr in nbrsdict.items():
...        if 'weight' in eattr:
...            # Do something useful with the edges
...            pass

But the edges reporting object is often more convenient:

>>> for u, v, weight in G.edges(data='weight'):
...     if weight is not None:
...         # Do something useful with the edges
...         pass


Simple graph information is obtained using object-attributes and methods. Reporting usually provides views instead of containers to reduce memory usage. The views update as the graph is updated similarly to dict-views. The objects nodes, `edges and adj provide access to data attributes via lookup (e.g. nodes[n], `edges[u, v], adj[u][v]) and iteration (e.g. nodes.items(), nodes.data('color'), nodes.data('color', default='blue') and similarly for edges) Views exist for nodes, edges, neighbors()/adj and degree.

For details on these and other miscellaneous methods, see below.

Subclasses (Advanced):

The Graph class uses a dict-of-dict-of-dict data structure. The outer dict (node_dict) holds adjacency information keyed by node. The next dict (adjlist_dict) represents the adjacency information and holds edge data keyed by neighbor. The inner dict (edge_attr_dict) represents the edge data and holds edge attribute values keyed by attribute names.

Each of these three dicts can be replaced in a subclass by a user defined dict-like object. In general, the dict-like features should be maintained but extra features can be added. To replace one of the dicts create a new graph class by changing the class(!) variable holding the factory for that dict-like structure. The variable names are node_dict_factory, adjlist_inner_dict_factory, adjlist_outer_dict_factory, and edge_attr_dict_factory.

node_dict_factory : function, (default: dict)
Factory function to be used to create the dict containing node attributes, keyed by node id. It should require no arguments and return a dict-like object
adjlist_outer_dict_factory : function, (default: dict)
Factory function to be used to create the outer-most dict in the data structure that holds adjacency info keyed by node. It should require no arguments and return a dict-like object.
adjlist_inner_dict_factory : function, optional (default: dict)
Factory function to be used to create the adjacency list dict which holds edge data keyed by neighbor. It should require no arguments and return a dict-like object
edge_attr_dict_factory : function, optional (default: dict)
Factory function to be used to create the edge attribute dict which holds attrbute values keyed by attribute name. It should require no arguments and return a dict-like object.

Typically, if your extension doesn’t impact the data structure all methods will inherited without issue except: to_directed/to_undirected. By default these methods create a DiGraph/Graph class and you probably want them to create your extension of a DiGraph/Graph. To facilitate this we define two class variables that you can set in your subclass.

to_directed_class : callable, (default: DiGraph or MultiDiGraph)
Class to create a new graph structure in the to_directed method. If None, a NetworkX class (DiGraph or MultiDiGraph) is used.
to_undirected_class : callable, (default: Graph or MultiGraph)
Class to create a new graph structure in the to_undirected method. If None, a NetworkX class (Graph or MultiGraph) is used.


Create a low memory graph class that effectively disallows edge attributes by using a single attribute dict for all edges. This reduces the memory used, but you lose edge attributes.

>>> class ThinGraph(nx.Graph):
...     all_edge_dict = {'weight': 1}
...     def single_edge_dict(self):
...         return self.all_edge_dict
...     edge_attr_dict_factory = single_edge_dict
>>> G = ThinGraph()
>>> G.add_edge(2, 1)
>>> G[2][1]
{'weight': 1}
>>> G.add_edge(2, 2)
>>> G[2][1] is G[2][2]

Please see ordered for more examples of creating graph subclasses by overwriting the base class dict with a dictionary-like object.


Adding and removing nodes and edges

DiGraph.__init__([incoming_graph_data]) Initialize a graph with edges, name, or graph attributes.
DiGraph.add_node(node_for_adding, **attr) Add a single node node_for_adding and update node attributes.
DiGraph.add_nodes_from(nodes_for_adding, **attr) Add multiple nodes.
DiGraph.remove_node(n) Remove node n.
DiGraph.remove_nodes_from(nodes) Remove multiple nodes.
DiGraph.add_edge(u_of_edge, v_of_edge, **attr) Add an edge between u and v.
DiGraph.add_edges_from(ebunch_to_add, **attr) Add all the edges in ebunch_to_add.
DiGraph.add_weighted_edges_from(ebunch_to_add) Add weighted edges in ebunch_to_add with specified weight attr
DiGraph.remove_edge(u, v) Remove the edge between u and v.
DiGraph.remove_edges_from(ebunch) Remove all edges specified in ebunch.
DiGraph.update([edges, nodes]) Update the graph using nodes/edges/graphs as input.
DiGraph.clear() Remove all nodes and edges from the graph.

Reporting nodes edges and neighbors

DiGraph.nodes A NodeView of the Graph as G.nodes or G.nodes().
DiGraph.__iter__() Iterate over the nodes.
DiGraph.has_node(n) Return True if the graph contains the node n.
DiGraph.__contains__(n) Return True if n is a node, False otherwise.
DiGraph.edges An OutEdgeView of the DiGraph as G.edges or G.edges().
DiGraph.out_edges An OutEdgeView of the DiGraph as G.edges or G.edges().
DiGraph.in_edges An InEdgeView of the Graph as G.in_edges or G.in_edges().
DiGraph.has_edge(u, v) Return True if the edge (u, v) is in the graph.
DiGraph.get_edge_data(u, v[, default]) Return the attribute dictionary associated with edge (u, v).
DiGraph.neighbors(n) Return an iterator over successor nodes of n.
DiGraph.adj Graph adjacency object holding the neighbors of each node.
DiGraph.__getitem__(n) Return a dict of neighbors of node n.
DiGraph.successors(n) Return an iterator over successor nodes of n.
DiGraph.succ Graph adjacency object holding the successors of each node.
DiGraph.predecessors(n) Return an iterator over predecessor nodes of n.
DiGraph.pred Graph adjacency object holding the predecessors of each node.
DiGraph.adjacency() Return an iterator over (node, adjacency dict) tuples for all nodes.
DiGraph.nbunch_iter([nbunch]) Return an iterator over nodes contained in nbunch that are also in the graph.

Counting nodes edges and neighbors

DiGraph.order() Return the number of nodes in the graph.
DiGraph.number_of_nodes() Return the number of nodes in the graph.
DiGraph.__len__() Return the number of nodes.
DiGraph.degree A DegreeView for the Graph as G.degree or G.degree().
DiGraph.in_degree An InDegreeView for (node, in_degree) or in_degree for single node.
DiGraph.out_degree An OutDegreeView for (node, out_degree)
DiGraph.size([weight]) Return the number of edges or total of all edge weights.
DiGraph.number_of_edges([u, v]) Return the number of edges between two nodes.

Making copies and subgraphs

DiGraph.copy([as_view]) Return a copy of the graph.
DiGraph.to_undirected([reciprocal, as_view]) Return an undirected representation of the digraph.
DiGraph.to_directed([as_view]) Return a directed representation of the graph.
DiGraph.subgraph(nodes) Return a SubGraph view of the subgraph induced on nodes.
DiGraph.edge_subgraph(edges) Returns the subgraph induced by the specified edges.
DiGraph.reverse([copy]) Return the reverse of the graph.