I am trying to calculate the sum/total value of each stacked bar in the chart and display it above each bar
https://jsfiddle.net/n0zjpyow/1/
Desired output:
(note:totals not accurate in image)
I am using the nest and rollup functions but the result from this is the total of each series and not each stacked bar.
var keys = d3.nest()
.key(function(d) { return (d.key) })
.rollup(function (v) {
return d3.keys(v[0]).filter(function(p, i){return i}) //filter out the heading
.reduce(function(s, p){ //sum each of the other members
//p is the category being summed
return (s[p] = d3.sum(d3.values(v[0][p][0])), s);
}, {});
})
.map(data);
Output
{1: {values: 190000000}
2A: {values: 152000000}
2B: {values: 190000000}
Non: {values: 128000000}}
I am getting confused with how to apply this to the data structure i have for the chart (which cannot be modified)
How can i calculate the total of the values in each bar ? Thanks for any assistance.
From your data, a simple approach to compute the total value of each bar could be the following:
var total = [0, 0, 0, 0, 0, 0];
data.forEach(e => {
e.values.forEach( (f, i) => {
total[i] = total[i] + f[1];
});
});
where you are going through each object (1
, 2A
, 2B
, Non
), and then, through each date (Jan '19 S
, Jan '19 U
, ..., Mar '19 U
). The result is accumulated in the array total
:
[ 660000000, 1015000000, 598000000, 484000000, 528000000, 396000000 ]
Regarding displaying the total of each bar, you can find a potential solution in this snippet:
https://jsfiddle.net/s5npfdo0/
with the following output:
Some points to take into account:
AFAIK, NVD3 doesn't allow to show the total value of each bar in a multibar graph (e.g., see this issue). The solution is to implement that part yourself. In my snippet, the implementation is quite simple, but it lacks some features, for example if you resize the window the total value positions are not recalculated. If this is a problem for your use case, I can try to solve it.
The function addTotalValue()
need to be called after the graph is completely drawn, because of that is called with setTimeout(addTotalValue, 500);
The yDomain computed automatically by NVD3 from data doesn't give space for the total value labels, so yDomain should be forced to another value: .yDomain([0, 1100e6])
. Here is computed 1100e6 manually and is only suitable for this data, but is shouldn't be difficult to compute automatically from data.