Dictionary object to decision tree in Pydot

11,661

Solution 1

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

Solution 2

Your question isn't entirely clear to me, but the way of accessing a dictionary key's value in Python is simply:

dictionary[key]

That will return to you that key's value. If that key is not in the dictionary, it will return a KeyError, so if you are working with dictionaries and you're not sure if the key you're requesting will be in the dictionary, you have two options.

If-statement (preferred):

if key in dictionary:
    return dictionary[key]

Try-catch:

try:
    return dictionary[key]
except KeyError:
    pass

If you don't know the keys in your dictionary and you need to get them, you can simply call dictionary.keys() and it will return a list of all of the keys in the dictionary.

Getting a the value of a dictionary key will return an object that could even be another object. Thus, to find out the value of "tofu", for example, we'd do the following:

menu['dinner']['vegetarian']['tofu']
# returns value 'good'
Share:
11,661
ono
Author by

ono

Updated on June 22, 2022

Comments

  • ono
    ono almost 2 years

    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?

  • ono
    ono over 11 years
    Let me rephrase: Notice that the value for 'dinner' has keys in it. How do I access values for those keys? Not sure if that's clear. How can I get the value for the key 'tofu' for instance?
  • ono
    ono over 11 years
    Yes, this is exactly what I'm working on. The only thing I want to change is to add another bubble for 'bad', 'average', ... under the corresponding node. This is great though.
  • ono
    ono over 11 years
    Also, where do I stick the graph.write_png('...')?
  • greeness
    greeness over 11 years
    I just add that to my code for completeness. Thanks for accepting the answer.
  • ono
    ono over 11 years
    Does this work for any dictionary data set? I tried a different data set and it doesn't seem to work
  • greeness
    greeness over 11 years
    For instance, If you have list in the dict, you need to take care of that as well in isinstance.
  • greeness
    greeness over 11 years
    Also I assume all keys and "simple" values are in type of string. Otherwise you need to name them correctly when adding edges to pydot.
  • Makiyo
    Makiyo over 6 years
    @greeness A question, if my content are in Mandarin, where can I encode? Thank you!
  • greeness
    greeness over 6 years
    Not sure I understand what you mean. But if you mean the name of each node is in Chinese, could you just replace the key/value with uncode strings for the dictionary?
  • miltonbhowmick
    miltonbhowmick almost 4 years
    graph.write_png('example1_graph.png'), this write_png function gives me below error. Can anyone help me out of the error? Error: "dot" with args ['-Tpng', 'C:\\Users\\MYPC~1\\AppData\\Local\\Temp\\tmptnelq9i2'] returned code: 1 stdout, stderr: b'' b'Format: "png" not recognized. No formats found.\r\nPerhaps "dot -c" needs to be run (with installer\'s privileges) to register the plugins?\r\n'
  • rosefun
    rosefun over 3 years
    Yes, I also meet the same error, FileNotFoundError: [Errno 2] "dot" not found in path.