【问题标题】:Sum of all the stacks of stacked bar chart in d3d3中所有堆叠条形图的总和
【发布时间】:2015-09-15 15:50:21
【问题描述】:

我有一个堆叠条形图,每个堆叠都有标签。现在我想在图表中每个条的顶部有另一个标签。我无法在栏的顶部放置标签,而且我得到了图表中所有值的总和,因为我想要每个栏的总和。 这是我的代码,

var groups = svg.selectAll("g.cost")
  .data(dataset.reverse())
  .enter().append("g")
  .attr("class", "cost")
  .style("fill", function (d, i) { return colors[i]; });
var sum = [0];

var svg = d3.select("svg");
var bar = groups.selectAll("g")
   .data(function (d) { return d; })
.enter().append("g")
  .attr("transform", function (d, i) { return "translate(0," + i * y(d.y0) - y(d.y0 + d.y) + ")"; });


bar.append("rect")
 .attr("x", function (d) { return x(d.x); })
 .attr("y", function (d) { return y(d.y0 + d.y); })
 .attr("height", function (d) { return y(d.y0) - y(d.y0 + d.y); })
 .attr("width", x.rangeBand())


bar.append("text")
    .attr("x", function (d) { return x(d.x); })
  .attr("y", function (d) { return y(d.y0 + d.y); })
    .attr("dy", ".35em")
    .attr('style', 'font-size:13px')
    .text(function (d) { if (d.y != 0) { sum += d.y; return "$" + d.y; } })
    .style('fill', 'black');

bar.append("text")
   .attr("x", function (d) { return x(d.x); })
 .attr("y", function (d) { return y(d.y0 + d.y); })
   .attr("dy", ".35em")
   .attr('style', 'font-size:13px')
   .text( sum)
   .style('fill', 'black'); 

jsfiddle:http://fiddle.jshell.net/1fsm8cst/3/

【问题讨论】:

  • 也许您可以包含一个带有示例数据的工作示例。直接在您的帖子中插入工作代码 sn-p 非常容易。
  • fiddle.jshell.net/1fsm8cst/2。请在这个小提琴中找到我的代码。
  • 您的小提琴中的标签值是正确的......每个标签都是单个条的值,而不是您声称的总数。
  • 我想在每个条的顶部有另一个标签,显示每个条的所有堆叠矩形的总和。
  • 我可能会遗漏一些东西,但我没有看到你在小提琴中尝试这样做......

标签: javascript d3.js graph


【解决方案1】:

由于堆栈布局按层分组,因此垂直汇总并不自然,但 d3 有很多功能可以提供帮助。在这种情况下,d3.nest、d3.sum 和 d3.values(关于 d3.sum 的真正好处是它忽略了 NaN 值)。有了这些,您可以按月汇总数据,然后您可以使用相同的坐标系和比例来定位汇总的元素。

var margin = {top: 20, right: 300, 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 + ")");



  /* Data in strings like it would be if imported from a csv */

  var data = [
    { month: "Jan", MobileCoupon: "430000", Bonus: "240000", Promotions: "200000", Merchandise: "150000" },
    { month: "Feb", MobileCoupon: "250000", Bonus: "440000", Promotions: "200000", Merchandise: "150000" },
    { month: "Mar", MobileCoupon: "350000", Bonus: "180000", Promotions: "200000", Merchandise: "150000" },
  ];

  var parse = d3.time.format("%b").parse;


  // Transpose the data into layers
  var dataset = d3.layout.stack()(["MobileCoupon", "Bonus", "Promotions", "Merchandise"].map(function(fruit) {
    return data.map(function(d) {
      return {x: parse(d.month), y: +d[fruit]};
    });
  }));

  var months = d3.nest()
    .key(function(d){return parse(d.month)})
    .rollup(function(leaves){
      return d3.sum(leaves, function(d) {return d3.sum(d3.values(d))});
    })
    .entries(data);

  // Set x, y and colors
  var x = d3.scale.ordinal()
    .domain(dataset[0].map(function(d) { return d.x; }))
    .rangeRoundBands([10, width-10], 0.35);

  var y = d3.scale.linear()
    .domain([0, d3.max(dataset, function(d) {  return d3.max(d, function(d) { return d.y0 + d.y; });  })])
    .range([height, 0]);

  var colors = ["#3D0000", "#d25c4d", "#f2b447", "#d9d574"];

  // Define and draw axes
  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")

    .ticks(5)
    .tickSize(-width, 0, 0)
    .tickFormat( d3.format("$,s") );

  var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .tickFormat(d3.time.format("%b"));

  svg.append("g")
    .attr("class", "y axis")
    .attr("transform", "translate(0,0)")
    .call(yAxis);


  svg.append("g")
    .call(xAxis)
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);

  // Create groups for each series, rects for each segment
  var groups = svg.selectAll("g.cost")
    .data(dataset)
    .enter().append("g")
    .attr("class", "cost")
    .style("fill", function(d, i) { return colors[i]; });

//  var svg = d3.select("svg");
  var bar = groups.selectAll("g")
    .data(function(d) { return d; })
    .enter().append("g")
    .attr("transform", function(d, i) {
      return "translate(" + x(d.x) + ", 0)";
    });

  var sum=0;
  bar.append("rect")
    .attr("y", function(d) { return y(d.y0 + d.y); })
    .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
    .attr("width", x.rangeBand())

  bar.append("text")
    .attr("x", -6)
    .attr("y", function(d) { return y(d.y0 + d.y); })
    .attr("dy", ".35em")
    .text(function(d) {sum+=d.y; return d3.format("$,s")(d.y); });

  columns = svg.append("g")
    .selectAll("text").data(months)
    .enter().append("text")
    .attr("x", function(d){
      return x(d.key) + x.rangeBand()/2
    })
    .attr("y", function (d) {
      return y(d.values);
    })
    .attr("dy", "1.35em")
    .attr('style', 'font-size:13px')
    .text( function (d){
      return d3.format("$,s")(d.values);
    })
    .style({fill: 'black', "text-anchor": "middle"});

  //  svg.call(tip);

  // Draw legend
  var legend = svg.selectAll(".legend")
    .data(colors)
    .enter().append("g")
    .attr("class", "legend")
    .attr("transform", function(d, m) { return "translate(90," + (m+5) * 20 + ")"; });

  legend.append("rect")
    .attr("x", width - 18)
    .attr("width", 18)
    .attr("height", 18)
    .style("fill", function(d, i) {return colors.slice().reverse()[i];});

  legend.append("text")
    .attr("x", width + 5)
    .attr("y", 9)
    .attr("dy", ".35em")
    .style("text-anchor", "start")
    .text(function(d, i) {
      switch (i) {
        case 0: return "Mobile Coupon";
        case 1: return "Bonus";
        case 2: return "Promotions";
        case 3: return "Merchandise";
      }
    });
svg {
      font: 10px sans-serif;
      shape-rendering: crispEdges;
    }

    .axis path,
    .axis line {
      fill: none;
      stroke: black;
      shape-rendering: crispEdges;
    }

    path.domain {
      stroke: none;
    }

    .y .tick line {
      stroke: #ddd;}


    text {
      font: 10px sans-serif;
      text-anchor: end;
    }



    .d3-tip {
      line-height: 1;
      font-weight: bold;
      padding: 12px;
      background: rgba(0, 0, 0, 0.8);
      color: #fff;
      border-radius: 2px;
    }

    /* Creates a small triangle extender for the tooltip */
    .d3-tip:after {
      box-sizing: border-box;
      display: inline;
      font-size: 10px;
      width: 100%;
      line-height: 1;
      color: rgba(0, 0, 0, 0.8);
      content: "\25BC";
      position: absolute;
      text-align: center;
    }

    /* Style northward tooltips differently */
    .d3-tip.n:after {
      margin: -1px 0 0 0;
      top: 100%;
      left: 0;
    }
    .legend
    {
      position: relative;
      top: -401px;
      left: 380px;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

【讨论】:

    【解决方案2】:

    我目前是 Javascript 和 D3 的初学者。 希望我的解决方案能达到目的: http://jsfiddle.net/sandeepedara/n3ew5sqq/

    var margin = {top: 20, right: 300, 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 + ")");
    
    
    
    /* Data in strings like it would be if imported from a csv */
    
    var data = [
      { month: "Jan", MobileCoupon: "430000", Bonus: "240000", Promotions: "200000", Merchandise: "150000" },
      { month: "Feb", MobileCoupon: "250000", Bonus: "440000", Promotions: "200000", Merchandise: "150000" },
      { month: "Mar", MobileCoupon: "350000", Bonus: "180000", Promotions: "200000", Merchandise: "150000" },
    ];
    
    for (var key in data) {
    var sum=0;
       if (data.hasOwnProperty(key)) {
           var obj = data[key];
    
            for (var prop in obj) {
    
              // important check that this is objects own property 
              // not from prototype prop inherited
              if(obj.hasOwnProperty(prop)){ 
                    if(prop=="month"){console.log("month");}
                    else{         
                     sum = sum + parseInt(obj[prop]);
                     obj.sum = sum;
                }
              }
           }
        }
    }
    
    var parse = d3.time.format("%b").parse;
    
    
    // Transpose the data into layers
    var dataset = d3.layout.stack()(["MobileCoupon", "Bonus", "Promotions", "Merchandise","sum"].map(function(fruit) {
      return data.map(function(d) {
        return {x: parse(d.month), y: +d[fruit]};
      });
    }));
    
    
    // Set x, y and colors
    var x = d3.scale.ordinal()
      .domain(dataset[0].map(function(d) { return d.x; }))
      .rangeRoundBands([10, width-10], 0.35);
    
    var y = d3.scale.linear()
      .domain([0, d3.max(dataset, function(d) {  return d3.max(d, function(d) { return d.y0 + d.y; });  })])
      .range([height, 0]);
    
    var colors = ["#3D0000", "#d25c4d", "#f2b447", "#d9d574"];
    
    // Define and draw axes
    var yAxis = d3.svg.axis()
      .scale(y)
      .orient("left")
    
      .ticks(5)
     .tickSize(-width, 0, 0)
      .tickFormat( function(d) { return "$" + d } );
    
    var xAxis = d3.svg.axis()
      .scale(x)
      .orient("bottom")
      .tickFormat(d3.time.format("%b"));
    
    svg.append("g")
      .attr("class", "y axis")
      .attr("transform", "translate(0,0)")
      .call(yAxis);
    
    
    svg.append("g")
    .call(xAxis)
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")");
      //.call(xAxis);
    
    
    // Create groups for each series, rects for each segment 
    var groups = svg.selectAll("g.cost")
      .data(dataset)
      .enter().append("g")
      .attr("class", "cost")
      .style("fill", function(d, i) { return colors[i]; });
    
    
    
    
      var svg = d3.select("svg");
      var bar = groups.selectAll("g")
         .data(function(d) { return d; })
      .enter().append("g")
        .attr("transform", function(d, i) { return "translate(0," + i * y(d.y0) - y(d.y0 + d.y) + ")"; });
    
    
     bar.append("rect")
      .attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y(d.y0 + d.y); })
      .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
      .attr("width", x.rangeBand())
    
    
    bar.append("text")
        .attr("x", function(d) { return x(d.x); })
      .attr("y", function(d) { return y(d.y0 + d.y); })
        .attr("dy", ".35em")
        .text(function(d) { return d.y; });
    
      svg.call(tip);
    
    
    
    
    
    // Draw legend
    var legend = svg.selectAll(".legend")
      .data(colors)
      .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, m) { return "translate(90," + (m+5) * 20 + ")"; });
    
    legend.append("rect")
      .attr("x", width - 18)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", function(d, i) {return colors.slice().reverse()[i];});
    
    legend.append("text")
      .attr("x", width + 5)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "start")
      .text(function(d, i) { 
        switch (i) {
          case 0: return "Mobile Coupon";
          case 1: return "Bonus";
          case 2: return "Promotions";
          case 3: return "Merchandise";
        }
      });
    

    【讨论】:

    • 你答错了。所需的输出如图所示。 pasteboard.co/1AeNB6X4.jpg
    • @AkshayShinde,我认为“Sum”这个词真的没有必要吗?
    猜你喜欢
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-04
    • 2015-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多