Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I process data that is nested multiple levels in D3?

Tags:

d3.js

I have following data structure

 { key: 'a', 
   values: { key: 'a0', 
             values: { key: 'a00',
                       values: {...}
                     },
                     { key: 'a01',
                       values: {...}
                     }
           },
           { key: 'a1', 
             values: {...}
           }
 }, 
 { key: 'b',
   values: {...}
 }

I see examples for processing two level nesting and could follow them to process the data. I just need to draw rectangles for each element with key property and determine its color and position based on some other properties of that object. Here is sample code close to what I want to do

var data = [
    {
        key : 'dept1',
        values : [
            {
                key : 'group-1-1',
                values : [
                    {
                        key : 'emp-1-1-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-1-1-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-1-1-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-1-1-4',
                        salary : 40000
                    }
                ]
            },
            {
                key : 'group-1-2',
                values : [
                    {
                        key : 'emp-1-2-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-1-2-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-1-2-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-1-2-4',
                        salary : 40000
                    }
                ]
            }
        ]
    },
    {
        key : 'dept2',
        values : [
            {
                key : 'group-2-1',
                values : [
                    {
                        key : 'emp-2-1-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-2-1-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-2-1-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-2-1-4',
                        salary : 40000
                    }
                ]
            },
            {
                key : 'group-2-2',
                values : [
                    {
                        key : 'emp-2-2-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-2-2-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-2-2-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-2-2-4',
                        salary : 40000
                    }
                ]
            }
        ]
    },
    {
        key : 'dept3',
        values : [
            {
                key : 'group-3-1',
                values : [
                    {
                        key : 'emp-3-1-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-3-1-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-3-1-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-3-1-4',
                        salary : 40000
                    }
                ]
            },
            {
                key : 'group-3-2',
                values : [
                    {
                        key : 'emp-3-2-1',
                        salary : 10000
                    },
                    {
                        key : 'emp-3-2-2',
                        salary : 20000
                    },
                    {
                        key : 'emp-3-2-3',
                        salary : 30000
                    },
                    {
                        key : 'emp-3-2-4',
                        salary : 40000
                    }
                ]
            }

        ]
    }
];

var svg = d3.select("body").append("svg").attr("width", "100%").attr("height", "100%");

var width = 200, height = 20, gap = 4, space = width + 2 * gap;

var sel = svg.selectAll("g").data(data).enter()
    .append("g")
    .attr("transform", function(d, i) {return 'translate(' + space * i + ', 0)'});

sel.append("rect").attr("x", gap).attr('y', gap).attr('width', width).attr('height', height)
    .attr('fill', 'green')
    .append('title').text(function(d) {return d.key});

var width1 = width/2 - gap;

var sel1 = sel.selectAll('g').data(function(d) {return d.values}).enter()
    .append('rect')
    .attr('x', function(p, i) {return gap + i * (width1+gap)}).attr('y', 2*gap + height)
    .attr('width', width1).attr('height', height)
    .attr('fill', 'blue')
    .append('title').text(function(p) {return p.key});

var width1 = width/4 - 3 * gap;

var sel2 = sel1.selectAll('g').data(function(d) {return d.values}).enter()
    .append('rect').text(function(k) {return k.key})
    .attr('x', function(p, i) {return gap + i * width1}).attr('y', 3*gap + 2*height)
    .attr('width', width1).attr('height', height)
    .attr('fill', 'cyan')
    .append('title').text(function(p) {return p.key});

I am expecting to draw three rows of rectangles. In this code first two rows show up correctly but third row does not show up at all. I looked in javascript console and looks like third row rectangles are getting appended to title of the second row rectangles. Hope this helps to show what I am asking here. Is this the way I should be looping here or is there a better way of doing it?

like image 252
John Smith Avatar asked Nov 03 '22 11:11

John Smith


1 Answers

Perhaps you could use a recursive solution similar to the one @nautat posted to answer my question about nested HTML tables with d3? https://stackoverflow.com/a/13412059/658053 I was able to modify it to fit my actual data and specs once I had the gist of doing recursion.

The trick is that you do a .filter on some condition, and either .call the recursive function on the cells that match the filter, or deal with the base-case on the items that match a different kind of filter.

Good luck!

like image 123
John St. John Avatar answered Nov 16 '22 17:11

John St. John