Creating a d3 horizontal bar chart with a multidimensional array/nested json file

1.2k views Asked by At

I'm trying to create a simple d3 bar chart (http://bost.ocks.org/mike/bar/2/) using the following nested json file.

 {
 "clustername": "cluster1",
 "children": [
 {
 "neighborhoodname": "Shaw",
 "children": [
    {

    "totpop2000": "1005",
    "children": [
    {
        "name": "demographic",
        "children": [
        {"name": "Black", "size2000":0.18},
        {"name": "White", "size2000":0.6},
        {"name": "Hispanic", "size2000":0.40},
        {"name": "Asian", "size2000":0.10}
        ]
        },
    {
        "name": "wellbeing",
        "children": [
        {"name": "Unemployment", "size2000":0.40},
        {"name": "Poverty", "size2000":0.1},
        {"name": "Without HS Education", "size2000":0.31}
        ]
        },
    {
        "name": "crime",
        "children": [
        {"name": "Violent Crime", "size2000":0.09},
        {"name": "Property Crime", "size2000":0.08}
        ]
        },
    {
        "name": "housing",
        "children": [
        {"name": "Home Ownership", "size2000":0.34},
        {"name": "Houses for Rent", "size2000":0.50}
        ]
    }
   ]
   }
  ]
  }
 ]
}

So far, my javascript includes the following for adding the amounts labeled as size2000 to the svg but when I run the code I can't seem to append the appropriate array of data (i.e. I get the first array/"clustername": "cluster1") in my json file.

var data = d3.json("data/test.json", function(json) {
 console.log(json); 

    
var bar = chart2000.selectAll("g")
      .data(data)
    .enter().append("g")
      .attr("transform", function(d, i) { return "translate(0," + i * height + ")"; });

  bar.append("rect")
      .attr("width", function(d) { return x((d.size2000)*100); })
      .attr("height", height - 1);

  bar.append("text")
      .attr("x", function(d) { return x((d.size2000)*100) - 3; })
      .attr("y", height / 2)
      .attr("dy", ".35em")
      .text(function(d) { return (d.size2000)*100); });

});

Is there a way to keep the json data structure and append the size2000 values to a svg? If so, how?

1

There are 1 answers

3
musically_ut On

One of the basic tenets of visualizations made using D3 is the correspondence between data and elements in the DOM. The mapping should also respect hierarchy of the data and DOM nodes, though it is not a strict requirement. Hence, if the data is nested, the visualization should be nested in some way as well (e.g. multiple bar charts divided by the hierarchy). Walking this analogy in the other direction, if you want a flat bar chart, then the data should also be a flat list of values.

It doesn't have to flat, but it would make the implementation and the DOM mapping easier. I would map the json data that you have manually for the bar chart into a flat list:

d3.json("data/test.json", function(json) {

    var barChartData = [];
    function addLeaves(node) {
        if (typeof node.children !== "undefined") { 
            node.children.forEach(addLeaves); 
        } else { 
            barChartData.push(node); 
        }
    }
    addLeaves(json);

    var bar = chart2000.selectAll("g")
              .data(barChartData)
    // ...
}