Reputation: 7150
I'm running into an issue when trying to implement a normalized stacked bar chart using D3v4.
The problem occurs due to my data format which contains nested object arrays populated dynamically on the server side.
var data = [{x:"data1", y:[{name:"red", value:10}, {name:"green", value:20}]},
{x:"data2", y:[{name:"red", value:30}, {name:"green", value:5}]}];
Calling d3.stack()
on this will not work since d3 doesn't know how to traverse into the object array y
. (https://jsfiddle.net/xv1qgqjg/)
Is there any way to tell d3.stack()
where to find the relevant data similar to the .data(function(d){ return d.y; })
used elsewhere?
Upvotes: 2
Views: 4378
Reputation: 102198
It doesn't seem to be possible. According to the documentation regarding stack(data[, arguments…]),
Any additional arguments are arbitrary; they are simply propagated to accessors along with the this object.
Thus, you'll have to change your data, creating an array which you can pass to d3.stack()
, such as this:
[{red:10,green:20},
{red:30,green:5}]
Given the data array in your question, there are several ways for creating the above-mentioned array. Here is my solution (the new array is called newData
):
newData = [];
data.forEach(d => {
var tempObj = {}
d.y.forEach(e => {
tempObj[e.name] = e.value;
})
newData.push(tempObj);
});
Here is a demo:
var data = [{x:"data1", y:[{name:"red", value:10}, {name:"green", value:20}]},
{x:"data2", y:[{name:"red", value:30}, {name:"green", value:5}]}];
newData = [];
data.forEach(d => {
var tempObj = {}
d.y.forEach(e => {
tempObj[e.name] = e.value;
})
newData.push(tempObj);
});
var stack = d3.stack()
.keys(["red", "green"])
.order(d3.stackOrderNone)
.offset(d3.stackOffsetExpand);
var series = stack(newData);
console.dir(series);
<script src="https://d3js.org/d3.v4.min.js"></script>
Upvotes: 5