Search code examples
javascriptobjectd3.jsnested-loops

D3 - How to loop through an object with keys for a bar chart


I am trying to create a bar chart with the dataset below. I am stuck on the part where the height[score] of the bar[country] is determined. How do I loop through the dataset to pull each score for a different country?

Any help would be greatly appreciated :)

var w = 500;
var h = 100;
var barPadding = 1;

var dataset = [
  {"country":"Hong Kong","score":8.98},
  {"country":"Singapore","score":8.54},
  {"country":"New Zealand","score":8.19},
  {"country":"Switzerland","score":8.09},
  {"country":"Mauritius","score":8.98},
  {"country":"United Arab Emirates","score":8.05},
  {"country":"Canada","score":8.00},
  {"country":"Australia","score":7.87},
  {"country":"Jordan","score":7.86},
  {"country":"Chile","score":7.84},
  ];

  //Create SVG element
  var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

  svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", function(d, i) {
      return i * (w / dataset.length);
    })
    .attr("y", function(d) {
      return h - (d * 4);
    })
    .attr("width", w / dataset.length - barPadding)
    .attr("height", function(d) {
      return d * 4;
    });

Solution

  • In D3, once you load the data through the .data(dataset) command, you can now access each record of the data by inserting the anonymous function function(d, i) { } as you have done in a few of your attributes.

    Since your dataset is:

    var dataset = [
      {"country":"Hong Kong","score":8.98},
      {"country":"Singapore","score":8.54},
      {"country":"New Zealand","score":8.19},
      {"country":"Switzerland","score":8.09},
      {"country":"Mauritius","score":8.98},
      {"country":"United Arab Emirates","score":8.05},
      {"country":"Canada","score":8.00},
      {"country":"Australia","score":7.87},
      {"country":"Jordan","score":7.86},
      {"country":"Chile","score":7.84},
      ];
    

    each d is a object record e.g. {"country":"Singapore","score":8.54}, while i refers to the index of the object d returned e.g. 1 for our example of d used above.

    To access the score of the object record d, this becomes simple Javscript object notation i.e. d.score.

    Hence your .attr call should look like:

    .attr("height", function(d) {
              return d.score * 4;
            });
    

    Similarly, you can extract the other fields e.g. country with d.country if you intend to use it in .attr("text", function(d) { return d.country; });

    This is the real beauty and power of D3. If you ever want to expand your visualization with more features that is obtained through your data, then all you have to make sure is that your dataset data contains more data attributes, and you can call them later as you iterate through the anonymous functions. And D3 is in the spirit of its name, truly being "data-driven"! :)