D3 – how to deal with JSON data structures?

When you join data to a selection via selection.data, the number of elements in your data array should match the number of elements in the selection. Your data array has two elements (for Jim and Ray), but the selection you are binding it to only has one SVG element. Are you trying to create multiple SVG elements, or put the score rects for both Jim and Ray in the same SVG element?

If you want to bind both data elements to the singular SVG element, you can wrap the data in another array:

var chart = d3.select("#charts").append("svg")
    .data([data])
    .attr("class", "chart")
    …

Alternatively, use selection.datum, which binds data directly without computing a join:

var chart = d3.select("#charts").append("svg")
    .datum(data)
    .attr("class", "chart")
    …

If you want to create multiple SVG elements for each person, then you’ll need a data-join:

var chart = d3.select("#charts").selectAll("svg")
    .data(data)
  .enter().append("svg")
    .attr("class", "chart")
    …

A second problem is that you shouldn’t use d3.values with an array; that function is for extracting the values of an object. Assuming you wanted one SVG element per person (so, two in this example), then the data for the rect is simply that person’s associated scores:

var rect = chart.selectAll("rect")
    .data(function(d) { return d.scores; })
  .enter().append("rect")
    …

If you haven’t already, I recommend reading these tutorials:

Leave a Comment