I am trying to build a hierarchical directed network where some nodes can branch into others, while others do not. The values in the inner dictionary (i.e. the integers) are to keep track of leaves in the tree-like structure. I've created a naive way to turn this particular nested dictionary graph_data into a directed graph but it is only specific to 3 layers. Below shows the hierarchy:

How can I create a nested function that adds edges to the directed graph for any number of levels? For example, if there was a level-3 or a level-4 this would not work and I would have to expand it out each time. Do I need to use a while loop?
import numpy as np
from collections import *
import networkx as nx
%matplotlib inline
# Hierarchical data
graph_data = {"root": {"level-0.A":0,
"level-0.B":{"level-1.B.1":2,
"level-1.B.2": {"level-2.B.2.1":3, "level-2.B.2.2":1}}}}
# Empty directed graph
G = nx.DiGraph()
# Helper functions
is_dict = lambda x: type(x) in {dict, OrderedDict, defaultdict}
# Iterate through the layers
for root, level_0 in graph_data.items():
if len(level_0) > 0:
for level_0_node, level_1 in level_0.items():
G.add_edge(root, level_0_node)
if is_dict(level_1):
for level_1_node, level_2 in level_1.items():
G.add_edge(level_0_node, level_1_node)
if is_dict(level_2):
for level_2_node, level_3 in level_2.items():
G.add_edge(level_1_node, level_2_node)
np.random.seed(8)
nx.draw(G, with_labels=True)

Use a queue to hold the details, e.g.:
from collections import Mapping
graph_data = {"root": {"level-0.A":0,
"level-0.B":{"level-1.B.1":2,
"level-1.B.2": {"level-2.B.2.1":3, "level-2.B.2.2":1}}}}
# Empty directed graph
G = nx.DiGraph()
# Iterate through the layers
q = list(graph_data.items())
while q:
v, d = q.pop()
for nv, nd in d.items():
G.add_edge(v, nv)
if isinstance(nd, Mapping):
q.append((nv, nd))
np.random.seed(8)
nx.draw(G, with_labels=True)

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With