Sorting a d3.js stacked bar chart

2020-07-27 04:42发布

问题:

Currently this stacked bar chart is sorted from left to right based on the total of each bar. How would I also sort each individual bar so that instead of sorting each individual bar by the key (i.e. Under 5 years old is at the bottom and 65 years and over is at the top) it would sort each individual bar by the value (largest at the bottom and smallest at the top).

For example:

Currently the CA bar is stacked like this (from bottom to top)

CA,2704659,4499890,2159981,3853788,10604510,8819342,4114496

I would like it stacked like this (from bottom to top)

CA,10604510,8819342,4499890,4114496,3853788,2704659,2159981

Just to be clear, I need to be able to do this on the client side (i.e. changing the order or format of the original data is not an option).

回答1:

The bar chart example you've linked to gets the order of the values directly from the CSV (through the domain of the colour scale). The actual stacking is done in this line:

d.ages = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });

The stacking order depends on the order the names are returned by color.domain(). To change the order, all you need to do is sort the values you're getting there. To sort them, for each bar individually, by the values of the individual segments, you can use

var order = color.domain().map(function(d) { return d; })
                 .sort(function(a, b) { return +d[b] - +d[a]; });

This gets the names from the domain of the colour scale and then sorts them in descending order by the values, which are referenced in the sort function. This new array order is then used for the stacking:

d.ages = order.map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });

The rest of the code remains unchanged. Complete demo here.