I'm using D3.js and I'm having trouble setting up a stacked layout for an area chart with multiple series. I have two possible structures of my data (if that helps). One is the raw data fed to the script, in this structure:
var data = [{key: 'Group1', value: 37, date: '04/23/12'},
{key: 'Group2', value: 12, date: '04/23/12'},
{key: 'Group3', value: 46, date: '04/23/12'},
{key: 'Group1', value: 32, date: '04/24/12'},
{key: 'Group2', value: 19, date: '04/24/12'},
{key: 'Group3', value: 42, date: '04/24/12'},
{key: 'Group1', value: 45, date: '04/25/12'},
{key: 'Group2', value: 16, date: '04/25/12'},
{key: 'Group3', value: 44, date: '04/25/12'},
{key: 'Group1', value: 24, date: '04/26/12'},
{key: 'Group2', value: 52, date: '04/26/12'},
{key: 'Group3', value: 64, date: '04/26/12'}]
Second is a nested structure, created using this code:
pData = d3.nest()
.key(function(d) { return d.key; })
.map(data);
Resulting in this structure:
pData = {Group1: [{date: 04/23/12, key: "Group1", value: 37},
{date: 04/24/12, key: "Group1", value: 32},
{date: 04/25/12, key: "Group1", value: 45},
...],
Group2: [{date: 04/23/12, key: "Group2", value: 12},
{etc, etc, etc}],
GroupX: [...] }
My questions is: How do I setup a d3.layout.stack()
generator, using one of the above data structures (or some variation), to create a stacked structure for my data such that I can pass it to an area generator similar to this:
var areaGenerator = d3.svg.area()
.interpolate('monotone')
.x(function(d) { return x(d.date); })
.y0(h)
.y1(function(d) { return y(d.value); });
You must feed an array of layers to the stack layout, so the first thing to change is to use nest.entries rather than nest.map. This returns an array of objects with a key
field (such as "Group1") and a values
array which contains the associated records. You would then specify a stack.values accessor so that the stack layout can access the values
array for each layer.
You will also need to define suitable x and y accessors to the stack layout so that it can understand your input data: the x-accessor should return d.date
, and the y-accessor should return d.value
. You will also need to convert your date strings to Dates; you can use d3.time.format to help with this. For example:
var format = d3.time.format("%m/%d/%y");
data.forEach(function(d) { d.date = format.parse(d.date); });
Lastly, change your area definition so that the baseline y0 is defined as y(d.y0)
and the topline y1 is defined as y(d.y0 + d.y)
.
Here's a working example:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With