Search code examples
pythonjsoncsvd3.jssunburst-diagram

Appending "size" element to last json child element for a sunburst diagram


I have a working python script that takes my csv columns data and converts it to a json file to be read by my d3 sunburst visualization. Problem is that there is no "size" element at the final child element which is needed to populate the sunburst diagram correctly.

Below is the script I have that reads the csv to a json the way I need it. I've tried modifying the script with an if else loop to find where there is no child element (the last element) and then appending on that element the "size: 1" but nothing happens.

This is example csv data. The code should work for anything though.

Energy, Grooming, Shedding, Trainability, Group, Breed

Regular Exercise, 2-3 Times a Week Brushing, Seasonal, Easy Training, Toy Group, Affenpinscher

enter image description here

import csv
from collections import defaultdict

def ctree():
return defaultdict(ctree)


def build_leaf(name, leaf):
res = {"name": name}

# add children node if the leaf actually has any children
if len(leaf.keys()) > 0:
    res["children"] = [build_leaf(k, v) for k, v in leaf.items()]

return res

def main():
tree = ctree()
# NOTE: you need to have test.csv file as neighbor to this file
with open('test.csv') as csvfile:
    reader = csv.reader(csvfile)
    for rid, row in enumerate(reader):
        if rid == 0:
            continue

        # usage of python magic to construct dynamic tree structure and
        # basically grouping csv values under their parents
        leaf = tree[row[0]]
        for cid in range(1, len(row)):
            leaf = leaf[row[cid]]

# building a custom tree structure
res = []
for name, leaf in tree.items():
    res.append(build_leaf(name, leaf))

# this is what I tried to append the size element
def parseTree(leaf):
   if len(leaf["children"]) == 0:
      return obj["size"] == 1
   else:
       for child in leaf["children"]:
           leaf['children'].append(parseTree(child))

# printing results into the terminal
import json
import uuid
from IPython.display import display_javascript, display_html, display
print(json.dumps(res, indent=2))

main()

The final child element needs to read something like this:

[
{
    "name": "Regular Exercise",
    "children": [
        {
            "name": "2-3 Times a Week Brushing",
            "children": [
                {
                    "name": "Seasonal",
                    "children": [
                        {
                            "name": "Easy Training",
                            "children": [
                                {
                                    "name": "Toy Group",
                                    "children": [
                                        {
                                            "name": "Affenpinscher",
                                            "size": 1
                                        }
                                    ]
                                }]}]}]}]}]}

Solution

  • To add size to the last entry:

    import csv
    from collections import defaultdict
    import json
    #import uuid
    #from IPython.display import display_javascript, display_html, display
    
    
    def ctree():
        return defaultdict(ctree)
    
    
    def build_leaf(name, leaf):
        res = {"name": name}
    
        # add children node if the leaf actually has any children
        if leaf.keys():
            res["children"] = [build_leaf(k, v) for k, v in leaf.items()]
        else:
            res['size'] = 1
    
        return res
    
    
    def main():
        tree = ctree()
        # NOTE: you need to have test.csv file as neighbor to this file
        with open('test.csv') as csvfile:
            reader = csv.reader(csvfile)
            header = next(reader)  # read the header row
    
            for row in reader:
                # usage of python magic to construct dynamic tree structure and
                # basically grouping csv values under their parents
                leaf = tree[row[0]]
    
                for value in row[1:]:
                    leaf = leaf[value]
    
        # building a custom tree structure
        res = []
    
        for name, leaf in tree.items():
            res.append(build_leaf(name, leaf))
    
        # printing results into the terminal
        print(json.dumps(res, indent=2))
    
    
    main()