4

I am new to d3.js and trying to build a stacked bar chart in which there would be positive and negative values for each tick along the x axis, but I cannot seem to figure out how to go about it. I was attempting to modify the example at http://bl.ocks.org/mbostock/1134768 to no avail.

somecallmemike
  • 441
  • 1
  • 8
  • 19
  • You set the domain of the (in this case) linear scale. It's hard to help more without a working example. I could point you here at least: https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear_domain – Marc Sep 05 '13 at 20:18
  • 1
    If every element needs to have two values visualized (positive and negative) you can try with something like this http://jsfiddle.net/cuckovic/hwDt3/ or if every element should have only positive or negative value you can filter negative values to go on a left side and leave positive on right side. – cuckovic Sep 05 '13 at 23:16

1 Answers1

4

I was having the same problem. After all I came with the following solution:

data.forEach(function (d) {
   var newD = {x: d[xcoord]};
   var y0neg = 0;
   var y0pos = 0;
   newD.values = color.domain().map(function (m) {
       if (d[m] > 0)
           return { name: m, y0: y0pos, y1: y0pos += +d[m] };
       else {
           var y1 = y0neg;
           return { name: m, y0: y0neg += d[m], y1: y1 };
       } 
   });
   newD.totalPositive = d3.max(newD.values, function (v) { return v.y1});
   newD.totalNegative = d3.min(newD.values, function (v) { return v.y0 });
   arranged.push(newD);
});

This is the way to arrange your data. I suppose that the variable d holds the values for each item for given x coordinate. The data collection is a list of values such as:

{
    'xcoord':'january',
    'gains': 100,
    'otherGains':20,
    'loses': -50
}

The names of the items to be show have to be mapped to the domain and then for each month we have to aggregate the data. For each item in given month I have a y0 and y1 coordinate. We have to have separate counter for negative and positive values in order to have correct y0 and y1 coordinates. Then the data is drawn this way:

state.selectAll("rect")
    .data(function (d) { return d.values; })
  .enter().append("rect")
    .attr("width", x.rangeBand())
    .attr("y", function (d) { return y(d.y1); })
    .attr("height", function (d) { return y(d.y0) - y(d.y1); })
    .style("fill", function (d) { return color(d.name); });

I have added stacked bar chart to my KoExtensions project https://github.com/hoonzis/KoExtensions you can check out directly the d3barChart method here: https://github.com/hoonzis/KoExtensions/blob/master/charting.js

Cheers

hoonzis
  • 1,717
  • 1
  • 17
  • 32