Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 - how to deal with JSON data structures?

I'm new to D3, and spent already a few hours to find out anything about dealing with structured data, but without positive result. I want to create a bar chart using data structure below. Bars are drawn (horizontally), but only for user "jim".

var data = [{"user":"jim","scores":[40,20,30,24,18,40]},             {"user":"ray","scores":[24,20,30,41,12,34]}];  var chart = d3.select("div#charts").append("svg")                                                  .data(data)               .attr("class","chart")               .attr("width",800)               .attr("height",350);  chart.selectAll("rect")         .data(function(d){return d3.values(d.scores);})         .enter().append("rect")     .attr("y", function(d,i){return i * 20;})     .attr("width",function(d){return d;})     .attr("height", 20); 

Could anyone point what I did wrong?

like image 477
Ray Avatar asked Apr 10 '12 09:04

Ray


1 Answers

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:

  • Thinking with Joins
  • Nested Selections
like image 104
mbostock Avatar answered Oct 20 '22 00:10

mbostock