d3中堆叠条形图的所有堆栈的总和 [英] Sum of all the stacks of stacked bar chart in d3

查看:117
本文介绍了d3中堆叠条形图的所有堆栈的总和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  var groups = svg.selectAll(g.cost)
.data(dataset.reverse())
.enter()。append(g)
.attr(class,cost)
.style(fill,函数(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){returntranslate(0,+ i * y(d.y0) - y(d.y0 + dy)+);});


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


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

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

jsfiddle: http://fiddle.jshell.net/1fsm8cst/3/ 因为堆叠分层,因此垂直汇总并不自然,但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。底部).append(g).attr(transform,translate(+ margin.left +,+ margin.top +)); / *如果从csv * / var data = [{month:Jan,MobileCoupon:430000,奖励:240000,促销:200000,商品:150000 },{month:Feb,MobileCoupon:250000,奖金:440000,促销:200000,商品:150000},{月:Mar,MobileCoupon:350000,奖励: 180000,促销:200000,商品:150000},]; var parse = d3.time.format(%b)。parse; //将数据转换为图层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 month = 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); //设置x,y和颜色var x = d3.scale.ordinal().domain(dataset [0] .map(function(d){return dx;})).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 + dy;});} )]).range([height,0]); var colors = [#3D0000,#d25c4d,#f2b447,#d9d574]; //定义和绘制轴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) ; //创建每个系列的组,每个片段的rects var groups = svg.selectAll(g.cost).data(dataset).enter()。append(g).attr(class,cost ).style(fill,function(d,i){return color [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(dx)+,0);}); var sum = 0; ()返回y(d.y0 + dy);}).attr(height, ) -  y(d.y0 + dy);}).attr(width,x.rangeBand())bar.append(text).attr(x,-6).attr(y ,function(d){return y(d.y0 + dy);}).attr(dy,.35em).text(function(d){sum + = dy; return d3.format( s)(dy);});数据(月).enter()。append(text).attr(x,函数(d){return x(d。))列= svg.append(g).selectAll 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); //绘制图例var legend = svg.selectAll(。legend).data(colors).enter()。append(g).attr(class,legend).attr(transform,函数(d,m){returntranslate(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开始).text(function(d,i){switch(i){case 0:returnMobile Coupon; case 1:returnBonus; case 2:returnPromotions; case 3:returnMerchandise ;}});  

svg {font:10px sans-衬线;形状渲染:crispEdges; } .axis路径,.axis行{fill:none;中风:黑色;形状渲染: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;填充:12px;背景:rgba(0,0,0,0.8);颜色:#fff; border-radius:2px; } / *为工具提示创建一个小三角形扩展器* / .d3-tip:{box-sizing:border-box;显示:内联; font-size:10px;宽度:100%; line-height:1;颜色:rgba(0,0,0,0.8);内容:\25BC;位置:绝对; text-align:center; } / *样式向北的工具提示不同* / .d3-tip.n:after {margin:-1px 0 0 0;顶部:100%;左:0; } .legend {position:relative;顶部:-401px;左:380px; }

< script src =https:// cdnjs .cloudflare.com / AJAX /库/ D3 / 3.4.11 / d3.min.js>< /脚本>


I have a stacked bar chart, which has labels in the every stack. Now I wanted to have another label at top of each bar in the graph. I am not able to place a label at the top of the bar, and also I am getting sum of all the values in the chart, where as I want sum for each bar. Here is my code,

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/

解决方案

Summarising vertically is not natural with the stack layout since it groups in layers, but d3 has plenty of functionality to help. In this case, d3.nest, d3.sum and d3.values (the really nice thing about d3.sum is that it ignores NaN values). With these you can summarise the data by month and then you can use the same coordinate system and scales to position the summarised elements.

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>

这篇关于d3中堆叠条形图的所有堆栈的总和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆