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 });

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:

    'gains': 100,
    '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:

    .data(function (d) { return d.values; })
    .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(; });

I have added stacked bar chart to my KoExtensions project you can check out directly the d3barChart method here:


Related Query

More Query from same tag