D3.js-JSON堆积的Barchart? [英] D3.js - Stacked Barchart from JSON?
问题描述
我一直在尝试重新创建这种提琴: https://jsfiddle.net/1c5eqrp3/3/
I have been trying to recreate this fiddle: https://jsfiddle.net/1c5eqrp3/3/
在我使用数据构建的水平堆积条形图的背景下。
In the context of a horizontal stacked bar chart that I am building using my data.
var bar1Data = [{
position: 1,
label: '70k',
value: 1708026
},
{
position: 2,
label: '71K - 149K',
value: 1915059
},
];
//sort bars based on value
bar1Data = bar1Data.sort(function(a, b) {
return d3.ascending(a.position, b.position);
})
var colors = ['green', 'blue'];
var bars = d3.select('#bars')
.append('svg')
.attr('width', 800)
.attr('height', 200);
bars.selectAll('rect')
.data(bar1Data)
.enter()
.append('rect')
.attr('width', function(d) {
return d;
})
.attr('x', function(d, i) {
return sum(bar1Data.value, 0, i);
})
.attr('fill', function(d, i) {
return colors[i];
})
.attr('y', 0)
.attr('height', 100);
function sum(array, start, end) {
var total = 0;
for (var i = start; i < end; i++) total += array[i];
return total;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id="bar"></div>
一切顺利,直到我试图让它读取我创建的bar1Data。
All was going well, until I tried to get it to read the bar1Data I created.
现在,我遇到了以下错误:
Now, I am getting the following errors:
Error: <rect> attribute width: Expected length, "[object Object]".
(anonymous) @ d3.js:1211
selection_each @ d3.js:1176
selection_attr @ d3.js:1233
(anonymous) @ bars3.js:23
Promise.then (async)
(anonymous) @ bars3.js:1
bars3.js:33 Uncaught (in promise) TypeError: Cannot read property '0' of undefined
at sum (bars3.js:33)
at SVGRectElement.<anonymous> (bars3.js:26)
at SVGRectElement.<anonymous> (d3.js:1209)
at Selection.selection_each [as each] (d3.js:1176)
at Selection.selection_attr [as attr] (d3.js:1233)
at bars3.js:25
我一直很努力地使用d3.v5创建堆叠的水平条形图。我一直在尝试使用d3.v4的各种示例,但无法使它们正常工作。这是我发现的最简单,最轻便的示例。但这还不包括秤(我希望稍后再放)。
I have been greatly struggling to create a stacked horizontal bar chart using d3.v5. I have been trying various examples using d3.v4 but I have not been able to get them to work. This was the simplest, most light-weight example I have found. But it does not yet include scales (which I shall hopefully put in a little later).
您能帮我解释一下这个问题吗?
Could you please help me to solve this issue with an explanation?
推荐答案
在 .attr('width',function(d){return d;})
中,您正在将条形图的宽度设置为整个对象 d
。您需要了解 .data(bar1Data)
为每个 bar1Data
值创建一个条目,并且该值是可访问的在所有这些函数中都为 d
。这意味着,一旦传递 .data(bar1Data)
,就不应再直接触摸该对象。
In .attr('width', function(d){ return d;})
, you're setting the width of the bar to the entire object d
. You need to understand that .data(bar1Data)
creates one entry per value of bar1Data
, and that that value is accessible as d
in all those functions. That means that, as soon as you've passed .data(bar1Data)
, you shouldn't directly touch that object anymore.
现在,从您的数据中,我似乎了解到您想使用前面所有条目的值来计算该点之前的累计总和。我将在答案中实现这一点,但同时也希望您指向 stack = d3.stack()
,它会为您完成此操作。
Now, from your data I seem to understand that you want to use the values of all preceding entries to calculate the cumulative sum up to that point. I will implement that in the answer, but would also like to point you towards stack = d3.stack()
, which does it for you.
另请注意,您的值太大。您需要使用一个域对其进行转换,否则每美元(或其他货币单位)将获得一个像素,这意味着条形图的绘制宽度是显示器右侧宽度的100倍。
Note also that your values are too large. You need to transform them using a domain, otherwise you get one pixel per dollar (or other unit of money), which means the bars are drawn 100x the width of your monitor to the right.
var bar1Data = [{
position: 1,
label: '70k',
value: 50
},
{
position: 2,
label: '71K - 149K',
value: 40
},
];
//sort bars based on value
bar1Data = bar1Data.sort(function(a, b) {
return d3.ascending(a.position, b.position);
})
var colors = ['green', 'blue'];
var bars = d3.select('#bars')
.append('svg')
.attr('width', 800)
.attr('height', 200);
bars.selectAll('rect')
.data(bar1Data)
.enter()
.append('rect')
.attr('width', function(d) {
return d.value;
})
.attr('x', function(d, i) {
// Note that I use `.map` here to take only the `.value` attribute
// from the data and create an array of numbers.
return sum(bar1Data.map((e) => e.value), 0, i);
})
.attr('fill', function(d, i) {
return colors[i];
})
.attr('y', 0)
.attr('height', 100);
function sum(array, start, end) {
var total = 0;
for (var i = start; i < end; i++) total += array[i];
return total;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<div id='bars'>
</div>
这篇关于D3.js-JSON堆积的Barchart?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!