Search code examples
pythondata-structuresdictionaryinfovis

Manipulating data structures in Python


I have data in JSON format:

data = {"outfit":{"shirt":"red,"pants":{"jeans":"blue","trousers":"khaki"}}}

I'm attempting to plot this data into a decision tree using InfoVis, because it looks pretty and interactive. The problem is that their graph takes JSON data in this format:

data = {id:"nodeOutfit",
    name:"outfit",
    data:{},
    children:[{
        id:"nodeShirt",
        name:"shirt",
        data:{},
        children:[{
            id:"nodeRed",
            name:"red",
                   data:{},
                   children:[]
        }],
     },  {
         id:"nodePants",
         name:"pants",
         data:{},
         children:[{
             id:"nodeJeans",
             name:"jeans",
             data:{},
             children:[{
                    id:"nodeBlue",
                    name:"blue",
                    data:{},
                    children[]
             },{
             id:"nodeTrousers",
             name:"trousers",
             data:{},
             children:[{
                    id:"nodeKhaki",
                    name:"khaki",
                    data:{},
                    children:[]
          }
    }

Note the addition of 'id', 'data' and 'children' to every key and value and calling every key and value 'name'. I feel like I have to write a recursive function to add these extra values. Is there an easy way to do this?

Here's what I want to do but I'm not sure if it's the right way. Loop through all the keys and values and replace them with the appropriate:

for name, list in data.iteritems():
    for dict in list:
        for key, value in dict.items():
            #Need something here which changes the value for each key and values
            #Not sure about the syntax to change "outfit" to name:"outfit" as well as
            #adding id:"nodeOutfit", data:{}, and 'children' before the value

Let me know if I'm way off.

Here is their example http://philogb.github.com/jit/static/v20/Jit/Examples/Spacetree/example1.html

And here's the data http://philogb.github.com/jit/static/v20/Jit/Examples/Spacetree/example1.code.html


Solution

  • A simple recursive solution:

    data = {"outfit":{"shirt":"red","pants":{"jeans":"blue","trousers":"khaki"}}}
    import json
    from collections import OrderedDict
    
    def node(name, children):
        n = OrderedDict()
        n['id'] = 'node' + name.capitalize()
        n['name'] = name
        n['data'] = {}
        n['children'] = children
        return n
    
    def convert(d):
        if type(d) == dict:
            return [node(k, convert(v)) for k, v in d.items()]
        else:
            return [node(d, [])]
    
    print(json.dumps(convert(data), indent=True))
    

    note that convert returns a list, not a dict, as data could also have more then one key then just 'outfit'.

    output:

    [
     {
      "id": "nodeOutfit", 
      "name": "outfit", 
      "data": {}, 
      "children": [
       {
        "id": "nodeShirt", 
        "name": "shirt", 
        "data": {}, 
        "children": [
         {
          "id": "nodeRed", 
          "name": "red", 
          "data": {}, 
          "children": []
         }
        ]
       }, 
       {
        "id": "nodePants", 
        "name": "pants", 
        "data": {}, 
        "children": [
         {
          "id": "nodeJeans", 
          "name": "jeans", 
          "data": {}, 
          "children": [
           {
            "id": "nodeBlue", 
            "name": "blue", 
            "data": {}, 
            "children": []
           }
          ]
         }, 
         {
          "id": "nodeTrousers", 
          "name": "trousers", 
          "data": {}, 
          "children": [
           {
            "id": "nodeKhaki", 
            "name": "khaki", 
            "data": {}, 
            "children": []
           }
          ]
         }
        ]
       }
      ]
     }
    ]