0
votes

I have a grouped stacked bar chart as looks in this image,http://pasteboard.co/1BKMicBq.jpg I want to add up the sum of the respective bars as in image. I have a dataset which has summed values ready for displaying, which looks like,

var months= [
{  "key": "Jan",
  "values[0]": 25000,
  "values[1]": 25000,
  "values[3]": 25000
       },  {  "key": "Feb",
  "values[0]": 25000,
  "values[1]": 25000,
  "values[3]": 25000
       },
         {  "key": "March",
  "values[0]": 25000,
  "values[1]": 25000,
  "values[3]": 25000
       }
 ]

I have tried it with following code, but i'm not able to get the data over the every bar.

var project_stackedbar = svg.selectAll(".project_stackedbar")
    .data(data)
  .enter().append("g")
    .attr("class", "g")
    .attr("transform", function (d) { return "translate(" + x0(d.Month) + ",0)"; });

project_stackedbar.selectAll("rect")
    .data(function (d) { return d.columnDetails; })
    .enter()
    .append("rect")
    .attr("width", x1.rangeBand())
    .attr("x", function (d) {
        return x1(d.column);
    })
    .attr("y", function (d) {
        return y(d.yEnd);
    })
    .attr("height", function (d) {
        return y(d.yBegin) - y(d.yEnd);
    })
    .style("fill", function (d) { return color(d.name); });
var sum = 0;

project_stackedbar.selectAll("text")
    .data(function (d) { return d.columnDetails; })
    .enter()
    .append("text")
    .attr("x", function (d) { return x1(d.column) })
    .attr("y", function (d) {
    return y(d.yEnd) + 15;})
    .text(function (d) {if (d.yEnd - d.yBegin !== 0) return "$" + (d.yEnd - d.yBegin);});

columns = svg.append("g")
      .selectAll("text")
    .data(months)
      .enter().append("text")
      .attr("x", function (d) {
          return (x1(d.column));
      })
      .attr("y", function (d, i) {
          return y(d.values[i]) - 60;
      })
      .attr("dy", "1.35em")
      .attr('style', 'font-size:13px')
      .text(function (d, i) {
          if (d.values !== 0) return d3.format("$")(d.values[i]);
      })
      .style({ fill: 'black', "text-anchor": "middle" });

Here i'm only able to get 3 values which will be printed in first group of the bars. I'm not able to get right x axis positions in the graph. can any one guide me here i'm going wrong?

1
Possible duplicate of this questionCool Blue
Cool Blue I had tried by looking at the same example, but i'm unable to assing var months values correctly. only first 3 values i'm getting.Nagendra Somayaji
OK, well, what's your thought process in not posting a working example? It's very easy to do it right here in the post using the code snippet tool.Cool Blue

1 Answers

0
votes

I assume the part of the code you are refering to is this...

  columns = svg.append("g")
    .selectAll("text")
    .data(months)
    .enter().append("text")
    .attr("x", function (d) {
      return (x1(d.column));
    })
    .attr("y", function (d, i) {
      return y(d.values[i]) - 60;
    })
    .attr("dy", "1.35em")
    .attr('style', 'font-size:13px')
    .text(function (d, i) {
      if (d.values !== 0) return d3.format("$")(d.values[i]);
    })
    .style({ fill: 'black', "text-anchor": "middle" });

This is the part that you tried to re-use from the example I linked and in that example it is doing the totals. Hence my assumption...

  1. You are binding the months variable from your post to text elements that you are creating on a g on svg
  2. You are referencing a member in that data called column which does not exist. You haven't included the code where you define the scale x1 but, assuming it is accepting dates, you could try x1(d3.time.format("%b").parse(d.key)) instead of x1(d.column).
  3. In the bound data you have stringified array references like "values[0]", but in your code you are referencing d.values[i] which does not exist in the data you provided. You need to sum the numeric values of the element like this: d3.sum(d3.values(d)).
  4. You are subtracting 60 from your y values which will probably push them outside the viewport, the totals are already being positioned with .attr("dy", "1.35em"), so if you need to adjust, do it there.

Given all of this, I would guess that you need something like this:

  var months= [
    {  "key": "Jan",
      "values[0]": 25000,
      "values[1]": 25000,
      "values[3]": 25000
    },  {  "key": "Feb",
      "values[0]": 15000,
      "values[1]": 25000,
      "values[3]": 25000
    },
    {  "key": "March",
      "values[0]": 5000,
      "values[1]": 25000,
      "values[3]": 25000
    }
  ];
  var margin = {top: 20, right: 50, bottom: 35, left: 50};

  var width = 760 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;



  var svg = d3.select("body")
    .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  var x1 = d3.scale.ordinal()
    .domain(months.map(function(d) { return d.key; }))
    .rangeRoundBands([10, width-10], 0.35);
  var y = d3.scale.linear()
    .domain([0, d3.max(months, function(d) {  return d3.sum(d3.values(d)); })])
    .range([height, 0]);

  columns = svg.append("g")
    .selectAll("text")
    .data(months)
    .enter().append("text")
    .attr("x", function (d) {
      return (x1(d.key));
    })
    .attr("y", function (d, i) {
      return y(d3.sum(d3.values(d)));
    })
    .attr("dy", "1.35em")
    .attr('style', 'font-size:13px')
    .text(function (d, i) {
      return d3.format("$")(d3.sum(d3.values(d)));
    })
    .style({ fill: 'black', "text-anchor": "middle" });
svg { outline: 1px solid black;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>