如何使用d3创建堆叠的条形图? [英] How to create a stacked barchart using d3?

查看:123
本文介绍了如何使用d3创建堆叠的条形图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个对象数组:

var data = [
  {"ORDER": 1, "apples": 3840, "bananas": 1920, "cherries": 960},
  {"ORDER": 2, "apples": 1600, "bananas": 1440, "cherries": 960},
  {"ORDER": 3, "apples":  640, "bananas":  960, "cherries": 640},
  {"ORDER": 4, "apples":  320, "bananas":  480, "cherries": 640}
];

我想创建一个堆积的条形图,以便订单在x轴上,而苹果,香蕉和樱桃的总和在y轴上. 到目前为止,这是我的代码:

I want to create a stacked bar chart so that the orders are on the x axis and the total of apples, bananas, and cherries are the y axis. Here is my code so far:

x = d3.scaleOrdinal().range([0, w-50])
y = d3.scaleLinear().range([0, h-50])

var stack = d3.stack()
    .keys(["apples", "bananas", "cherries", "dates"])
    .order(d3.stackOrderNone)
    .offset(d3.stackOffsetNone);

var series = stack(data);

 x.domain(series.map(function(d) { return d.Order; }));
 y.domain([0, d3.max(data, function(d) { return d; })]).nice();

g.append("g")
    .selectAll("g")
    .data(d3.stack()(series))
    .enter().append("g")
        .attr("fill", function(d) { return color(d.key); })
    .selectAll("rect")
    .data(function(d) { return d; })
    .enter().append("rect")
        .attr("x", function(d) { return x(d.Order); })
        .attr("y", function(d) { return y(d[1]); })
        .attr("height", function(d) { return y(d[0]) - y(d[1]); })
        .attr("width", x);  

我也将它附加到svg上,但是我知道问题出在上面的代码中.有什么想法我做错了吗?

I am also appending it to an svg but I know the problem is in the code above. Any ideas on what im doing wrong?

推荐答案

存在一些问题.

一个,您的图表数据已经准备好堆放在series中:

One, your data for the chart is already ready stacked in series:

var series = stack(data);

此:d3.stack()(series);将产生一个空数组:

This: d3.stack()(series); will produce an empty array:

var data = [
  {"ORDER": 1, "apples": 3840, "bananas": 1920, "cherries": 960},
  {"ORDER": 2, "apples": 1600, "bananas": 1440, "cherries": 960},
  {"ORDER": 3, "apples":  640, "bananas":  960, "cherries": 640},
  {"ORDER": 4, "apples":  320, "bananas":  480, "cherries": 640}
];
var stack = d3.stack()
    .keys(["apples", "bananas", "cherries"])
    .order(d3.stackOrderNone)
    .offset(d3.stackOffsetNone);
var series = stack(data);
console.log(d3.stack()(series));

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.js"></script>

进一步:

 .attr("x", function(d) { return x(d.Order); })

这将返回未定义.首先,您的财产是ORDER而不是Order,其次,如果您在返回之前console.log(d),您会注意到财产顺序位于:d.data.ORDER.

This will return undefined. First, your property is ORDER not Order, and secondly, if you console.log(d) before that return, you'll notice that the property order is located at: d.data.ORDER.

这也是您体重秤的问题:

This is also an issue with your scale:

 x.domain(series.map(function(d) { return d.Order; }));

对于x标度域,应使用data变量来映射x域:x.domain(data.map(function(d) { return d.ORDER; }));.

For your x scale domain, you should use your data variable to map out the x domain: x.domain(data.map(function(d) { return d.ORDER; }));.

说到比例尺,最好用scaleBand() (文档)而不是scaleOrdinal(),这将允许您使用x.bandwidth()设置宽度.

Speaking of scales, your width is best defined with a scaleBand() (documentation) rather than a scaleOrdinal(), this will allow you to set the width with x.bandwidth().

最后,仍然谈到体重秤: 就您的规模而言,如果使用此bl.ock为例,您将看到创建一个total属性,该属性将定义域的上端.因此,您将需要找到一种方法来获取要为每个ORDER绘制图形的所有属性的总数.我使用了任意10000作为上限来生成一个有效的示例(我也不知道您的颜色函数,所以我只使用了一个数组):

Lastly, still speaking of scales: For your y scale, your domain will not work properly, if using this bl.ock as an example, you'll see the creation of a total property that will define the upper end of the domain. So you will need to find a way to get the total of all the properties you want to graph for each ORDER. I've used an arbitrary 10 000 as the upper limit to produce a working example (I also don't know your color function, so I've just used an array):

var data = [
  {"ORDER": 1, "apples": 3840, "bananas": 1920, "cherries": 960},
  {"ORDER": 2, "apples": 1600, "bananas": 1440, "cherries": 960},
  {"ORDER": 3, "apples":  640, "bananas":  960, "cherries": 640},
  {"ORDER": 4, "apples":  320, "bananas":  480, "cherries": 640}
];

var h = 200;
var w = 200;
var svg = d3.select('body').append('svg').attr('width',w).attr('height',h);
var g = svg.append('g');


var x = d3.scaleBand().rangeRound([0, w-50]);
var y = d3.scaleLinear().range([h-50, 0]).domain([0,10000]);
var color = ['#bae4bc','#7bccc4','#43a2ca'];

var stack = d3.stack()
    .keys(["apples", "bananas", "cherries"])
    .order(d3.stackOrderNone)
    .offset(d3.stackOffsetNone);
    
var series = stack(data);

x.domain(data.map(function(d) { return d.ORDER; }));

g.append("g")
    .selectAll("g")
    .data(series)
    .enter().append("g")
        .attr("fill", function(d,i) { return color[i]; })
    .selectAll("rect")
    .data(function(d) { return d; })
    .enter().append("rect")
        .attr("x", function(d) { return x(d.data.ORDER); })
        .attr("y", function(d) { return y(d[1]); })
        .attr("height", function(d) { return y(d[0]) - y(d[1]); })
        .attr("width", x.bandwidth());

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.6.0/d3.js"></script>

这篇关于如何使用d3创建堆叠的条形图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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