Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to build directed graph from nested dictionary? (Python 3 | NetworkX)

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: enter image description here

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)

enter image description here

like image 324
O.rka Avatar asked May 18 '26 14:05

O.rka


1 Answers

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)

enter image description here

like image 126
AChampion Avatar answered May 21 '26 02:05

AChampion



Donate For Us

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