Dictionary object to decision tree in Pydot

ono picture ono · Dec 3, 2012 · Viewed 8.8k times · Source

I have a dictionary object as such:

menu = {'dinner':{'chicken':'good','beef':'average','vegetarian':{'tofu':'good','salad':{'caeser':'bad','italian':'average'}},'pork':'bad'}}

I'm trying to create a graph (decision tree) using pydot with the 'menu' data this.

'Dinner' would be the top node and its values (chicken, beef, etc.) are below it. Referring to the link, the graph function takes two parameters; a source and a node.

It would look something like this:

Except 'king' would be 'dinner' and 'lord' would be 'chicken', 'beef', etc.

My question is: How do I access a key in a value? To create a tree from this data I feel like I need to create a loop which checks if there is a value for a specific key and plots it. I'm not sure how to call values for any dictionary object (if it's not necessarily called 'dinner' or have as many elements.).

Any suggestions on how to graph it?

Answer

greeness picture greeness · Dec 3, 2012

Using a recursive function

You might want to consider using a recursive function (like the visit in my code below, so that you are able to process a general nested dictionary. In this function, you want to pass a parent parameter to keep track of who is your incoming node. Also note you use isinstance to check if the dictionary value of a key is a dictionary of its own, in that case you need to call your visit recursively.

import pydot

menu = {'dinner':
            {'chicken':'good',
             'beef':'average',
             'vegetarian':{
                   'tofu':'good',
                   'salad':{
                            'caeser':'bad',
                            'italian':'average'}
                   },
             'pork':'bad'}
        }

def draw(parent_name, child_name):
    edge = pydot.Edge(parent_name, child_name)
    graph.add_edge(edge)

def visit(node, parent=None):
    for k,v in node.iteritems():
        if isinstance(v, dict):
            # We start with the root node whose parent is None
            # we don't want to graph the None node
            if parent:
                draw(parent, k)
            visit(v, k)
        else:
            draw(parent, k)
            # drawing the label using a distinct name
            draw(k, k+'_'+v)

graph = pydot.Dot(graph_type='graph')
visit(menu)
graph.write_png('example1_graph.png')

Resulting tree structure

enter image description here