Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

d3 JSON multiple line chart

I'm trying to make a plot with multiple lines on it from a JSON blob that looks like:

{"2007": [{"val":10, "mon":10}, {"val":20, "mon":11}, {"val":40, "mon":12}, ...],
 "2008": [{"val":20, "mon":8}, {"val":20, "mon":9}, {"val":40, "mon":10}, ...],
  ...
 "2012": [{"val":40, "mon":8}, {"val":50, "mon":9}, {"val":60, "mon":10}, ...]
}

The data is basically monthly totals for each year, with some years not having data for some months. I can't figure out exactly how to parse the data in d3 though. I tried various ways such as

var line = d3.svg.line()
 .interpolate("basis")
.x(function(d) { return x(d.mon); })
.y(function(d) { return y(d.val); });

svg.selectAll(".line")
 .data(series)
 .enter().append("path")
 .attr("class", "line")
 .attr("d", line);

But I can't seem to get the data into the SVG line. Any suggestions? Is there a better way to structure the JSON?

like image 848
reptilicus Avatar asked Jun 16 '26 13:06

reptilicus


2 Answers

Here's what worked out in case anyone else runs across this problem. The trick is to pass a function that returns the values in the associative array in the "d" attribute of the path element.

  entries = d3.entries(data);

  var colors = d3.scale.category20()
    .domain(d3.keys(data));

  var line = d3.svg.line()
    .interpolate("basis")
    .x(function(d) { return x(d.month) })
    .y(function(d) { return y(d.value) });

  svg1.selectAll(".line")
    .data(entries)
  .enter().append("path")
    .attr("class", "line")
    // function(d), not just line function 
    .attr("d", function(d){ return  line(d.value); })
    .attr("stroke", function(d) { return colors(d.key) });

Some help from this answer too: Using nested data with javascript D3 problem

like image 120
reptilicus Avatar answered Jun 18 '26 04:06

reptilicus


My guess is that the biggest problem here is that you're starting with an object, not an array. d3.data takes an array, not an object, so you might need your data set up like:

[
  [{"val":10, "mon":10}, {"val":20, "mon":11}, {"val":40, "mon":12}, ...],
  [{"val":20, "mon":8}, {"val":20, "mon":9}, {"val":40, "mon":10}, ...],
  ...
]

If you need to convert your current data to this format, look at d3.entries, which will give you an array with your key as well as your array of points:

[
  {
    key: "2008",
    value: [{"val":10, "mon":10}, {"val":20, "mon":11}, {"val":40, "mon":12}, ...]
  },
  { 
    key: "2008",
    value: [{"val":20, "mon":8}, {"val":20, "mon":9}, {"val":40, "mon":10}, ...]
  },
  ...
]

See this fiddle for a simple-case version of your graph, using the first data format above: http://jsfiddle.net/nrabinowitz/kmmyc/

like image 38
nrabinowitz Avatar answered Jun 18 '26 03:06

nrabinowitz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!